一.Docker镜像简介
Docker的镜像概念类似于虚拟机里的镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。
例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了Mysql或用户需要的其它应用程序。
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统被称为UnionFS
。镜像可以基于Dockerfile
构建,Dockerfile是一个描述文件,里面包含若干条命令,每条命令都会对基础文件系统创建新的层次结构。
Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
二.Docker镜像的分层
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。分层时有文件更新直接替换,基础镜像一样时直接拿过来复用。
- Dockerfile中的每个指令都会创建一个新的镜像层
- 镜像层将被缓存和复用
- 当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
- 某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效
- 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件
优点:
最大的一个好处就是 - 共享资源
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
三.Docker镜像的创建方法
- 基于已有镜像创建
- 基于本地模板创建
- 基于Dockerfile创建
基于已有镜像创建
将容器里面运行的程序及运行环境打包生成新的镜像
docker commit [选项]容器ID/名称仓库名称:[标签]
●-m 说明信息
●-a 作者信息
●-p 生成过程中停止容器的运行
基于本地模板创建
- 通过导入操作系统模板文件生成新的镜像
- 使用wget命令导入为本地镜像
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
导入成功后可查看本地镜像信息
docker images | grep new
基于Dockerfile创建
Dockerfile是由一组指令组成的文件
Dockerfile结构四部分
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
Dockerfile每行支持一条指令,每条指令可以携带多个参数,支持使用以#开头的注释
Dockerfile操作指令
指令 | 含义 |
FROM镜像 | 指定新镜像所基于的镜像,第一条指令必须为FROM指令 , 每创建一个镜像就需要一 条FROM指令。 |
MAINTAINER名字 | 说明新镜像的维护人信息 |
CMD[”要运行的程序",”参数1, “参数2 "] | 指令启动容器时要运行的命令或者脚本,Dockerfile只能有 -条CMD命令,如果指定多条则只能最后一条被执行 |
EXPOSE端口号 | 指定新镜像加载到Docker时要开启的端口 |
ENV环境变量变量值 | 设置一个环境变量的值,会被后面的RUN使用 |
ADD源文件/目录目标文件/目录 | 将源文件复制到目标文件,源文件要与Dockerfile位于相同 目录中,或者是一个URL |
COPY源文件/目录目标文件/目录 | 将本地主机上的文件/目录复制到目标地点,源文件/目录要 与Dockerfile在相同的目录中 |
VOLUME[“目录"] | 在容器中创建一个挂载点 |
USER用户名/UID | 指定运行容器时的用户 |
WORKDIR路径 | 为后续的RUN、CMD、ENTRYPOINT指定工作目录 |
ONBUILD命令 | 指定所生成的镜像作为一个基础镜像时所要运行的命令 |
HEALTHCHECK | 健康检查 |
RUN命令 | 在所基于的镜像上执行命令,并提交到新的镜像中 |
四.案例
1.基于已有镜像创建
[root@localhost ~]# docker create -it centos:7 /bin/bash
9ab4a4428d6b5124f414c19a0e6a5f547e513c2e4d48174f95f07a0ffe0ae771
[root@localhost ~]# docker ps -a ##查看容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9ab4a4428d6b centos:7 "/bin/bash" 6 seconds ago Created
[root@localhost ~]# docker commit -m "new" -a "moont" 9ab4a4428d6b moont:new
sha256:d1dedd58021ececfff93b16e2d6d68c337ce0f0dbc54a6d7fb3a797736368e4b
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
moont new d1dedd58021e 33 seconds ago 204MB
nginx moon 3a23aa75b84b 22 hours ago 131MB
tomcat latest e0bd8b34b4ea 7 days ago 649MB
centos 7 8652b9f0cb4c 12 days ago 204MB
注:推荐先停止容器再进行创建
[root@localhost ~]# docker commit -m "new" -a "moont1" -p 9ab4a4428d6b moont1:new
基于本地模板创建
[root@localhost ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - tes:jac
sha256:73c00fb16e312cf973e4815390081fb74d12ba6fbe8b55bc67eed0d3cb22c33b
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tes jac 73c00fb16e31 18 seconds ago 215MB
基于Dockerfile创建
[root@localhost ~]# mkdir apache
[root@localhost ~]# cd apache/
[root@localhost apache]# vim Dockerfile
FROM centos:7 ##基于的基础镜像
MAINTAINER This is my home ## 维护镜像的用户信息
RUN yum -y update ##更新yum
RUN yum -y install httpd ##安装apache
EXPOSE 80 ##开启80端口
ADD index.html /var/www/html/index.html ##复制网站首页文件
ADD run.sh /run.sh ##将执行的脚步复制到镜像中
RUN chmod 755 /run.sh ##给脚本运行权限
CMD ["/run.sh"] ##启动容器时执行脚本
[root@localhost apache]# vim run.sh
#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND
[root@localhost apache]# docker build -t httpd:centos . ##生成镜像
[root@localhost apache]# docker run -d -p 1216:80 httpd:centos ##新镜像运行容器
a7fb96c19a1b4aead2b57e85ea18e279ef61f0de2574f6e31ec6c302f2016f61
[root@localhost apache]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7fb96c19a1b httpd:centos "/run.sh" 57 seconds ago Up 56 seconds 0.0.0.0:1216->80/tcp hungry_villani
测试
私有仓库
私有仓库优点
- 节省网络带宽,针对于每个镜像不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可;
- 提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用。
搭建私有仓库
[root@localhost apache]# docker pull registry ##下载registry
[root@localhost apache]# vim /etc/docker/daemon.json
{
"insecure-registries": ["192.168.100.13:5000"],
"registry-mirrors": ["https://wy3fhvf9.mirror.aliyuncs.com"]
}
[root@localhost apache]# systemctl restart docker.service ##重启docker服务
[root@localhost apache]# docker create -it registry /bin/bash ##创建容器
启动私有仓库服务
[root@localhost apache]# docker run -d -p 5000:5000 registry
65b1c4d2f54e380477d609ed116700ecd9510eb1f003ad938ae2caf805da6621
[root@localhost apache]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65b1c4d2f54e registry "/entrypoint.sh /etc…" 3 seconds ago Up 2 seconds 0.0.0.0:5000->5000/tcp fervent_khayyam
将宿主机的/data/registry自动创建挂载容器中的/tmp/registry
[root@localhost apache]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
ef1d5b36337a511de8a2cdd85aa03b0bbfff52c8a1047958e544a086ee67d55b
[root@localhost apache]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef1d5b36337a registry "/entrypoint.sh /etc…" 10 seconds ago Up 9 seconds 0.0.0.0:500->5000/tcp nice_yalow
更改标记为192.168.100.13:5000/abc
[root@localhost ~]# docker tag tes:jac 192.168.100.13:5000/abc
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.100.13:5000/abc latest 73c00fb16e31 2 hours ago 215MB
上传镜像至私有仓库
[root@localhost ~]# docker push 192.168.100.13:5000/abc
The push refers to repository [192.168.100.13:5000/abc]
3a1d67a7fe13: Pushed
latest: digest: sha256:84ae9235ab88049a0de4a1cc8ade7af198c16acf031048d9f33278d1627bd84d size: 528
[root@localhost ~]# curl -XGET http://192.168.100.13:5000/v2/_catalog
{"repositories":["abc"]}
私有仓库下载镜像
[root@localhost ~]# docker pull 192.168.100.13:5000/abc
Using default tag: latest
latest: Pulling from abc
Digest: sha256:84ae9235ab88049a0de4a1cc8ade7af198c16acf031048d9f33278d1627bd84d
Status: Image is up to date for 192.168.100.13:5000/abc:latest
192.168.100.13:5000/abc:latest
创建数据卷
[root@localhost ~]# docker run -v /var/www:/data1 --name web1 -it centos:7 /bin/bash
[root@75aa9eafde42 /]# ll
total 12
-rw-r--r--. 1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx. 1 root root 7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x. 2 root root 6 Nov 26 09:27 data1 ##数据卷
测试
[root@75aa9eafde42 /]# cd /data1/
[root@75aa9eafde42 data1]# touch once ##数据卷下创建文件
[root@75aa9eafde42 data1]# ll
total 0
-rw-r--r--. 1 root root 0 Nov 26 09:29 once
[root@localhost ~]# ll /var/www/ ##宿主机上查看已同步
总用量 0
-rw-r--r--. 1 root root 0 11月 26 17:29 once
数据卷容器
使用背景
生产环境中使用Docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。
容器中管理数据主要有两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。
- 数据卷容器(Data Volume Containers):使用特定容器维护数据卷。如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复。
案例实操
运行容器boss并建立俩个数据卷
[root@localhost ~]# docker run --name boss -v /data1 -v /data2 -it centos:7 /bin/bash
数据卷下创建俩个文件测试
[root@8fa060d8b40a /]# touch /data1/gg
[root@8fa060d8b40a /]# touch /data2/gg
运行容器xiye并挂载boss数据卷
[root@localhost ~]# docker run -it --volumes-from boss --name xiye centos:7 /bin/bash
[root@63eee77e18b0 /]# ll /data1 ##发现文件已经同步
total 0
-rw-r--r--. 1 root root 0 Nov 26 09:37 gg
[root@63eee77e18b0 /]# ll /data2
total 0
-rw-r--r--. 1 root root 0 Nov 26 09:37 gg
容器互联
[root@localhost ~]# docker run -itd -P --name boss1 centos:7 /bin/bash ##创建并运行容器boss1
[root@localhost ~]# docker run -itd -P --name boss2 --link boss1:boss1 centos:7 /bin/bash ##创建容器boss2运行 进行link关联
测试
[root@localhost ~]# docker exec -it f079b9213db2 /bin/bash ##进入boss2
[root@f079b9213db2 /]# ping boss1
PING boss1 (172.17.0.3) 56(84) bytes of data.
64 bytes from boss1 (172.17.0.3): icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from boss1 (172.17.0.3): icmp_seq=2 ttl=64 time=0.066 ms
^C