文章目录
- 一、 怎么了解镜像
- 1.1 镜像的分层
- 1.2 镜像分层的特点
- 1.3 镜像的创建
- 1.3.1 基于Dockerfile创建((其中dockerfile为重点,也最常用)
- Dockerfile操作指令
- 1.3.2 基于已有的镜像容器进行创建镜像
- 1.3.3 基于本地模板进行构建
- 二、 docker的数据管理
- 2.1 数据卷
- 2.2 数据卷容器
- 三、 搭建私有仓库
- 3.1 搭建仓库
- 3.2 上传、下载私有仓库中的镜像
- 四、 容器间通信
- 4.1 实现容器之间的通信
- 4.2 通过中转网卡连接,实现互通(注:只能用于最新版本的centos)
一、 怎么了解镜像
1.1 镜像的分层
在 Docker 的术语里,一个只读层被称为镜像,一个镜像是永久不会变的。
由于 Docker 使用一个统一文件系统,Docker 进程认为整个文件系统是以读写方式挂载的。 但是所有的变更都发生顶层的可写层,而下层的原始的只读镜像文件并未变化,所以Docker镜像是分层的。
- 第一层必须是FROM,FROM后面跟一个基础镜像,比如FROM centos:7
- 第二层ADD,从宿主系统往镜像容器中添加指定文件,可以在宿主系统上写一个脚本,然后通过ADD指令添加到容器中执行。
- 第三层VOLUME,可以使用宿主系统的资源空间,类似于共享挂载,宿主系统提供一个存储空间,存储空间中可以放各种文件、软件包,容器可以直接挂载使用。类似于Linux系统的共享挂载。
- 第四层CMD,启动容器。CMD后面可以跟一个脚本或者命令。
1.2 镜像分层的特点
- Dockerfile中的每个指令都会创建一个新的镜像层
- 镜像层将被缓存和复用
- 当Dockerfile的指令修改了,复制的文件当Dockerfile的指令修改了,复制的文件了,对应的镜像层缓存就会失效。
- 某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效
- 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件。
1.3 镜像的创建
docker环境部署在之前的博客中已经体现,这里就不再进行操作,直接开始镜像的创建。
镜像制作有三种方式:
1.3.1 基于Dockerfile创建((其中dockerfile为重点,也最常用)
Dockerfile是由一组指令组成的文件
Dockerfile结构四部分
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#"号开头的注释。
Dockerfile操作指令
指令 | 含义 |
FROM 镜像 | 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令 |
MAINTAINER 名字 | 说明新镜像的维护人信息 |
RUN 命令 | 在所基于的镜像执行命令,并提交到新的镜像中 |
CMD [ “要运行的程序”,“参数1”,“参数2”] | 指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能执行最后一条 |
EXPOSE 端口号 | 指定新镜像加载到Docker时要开启的端口 |
ENV 环境变量 变量值 | 设置一个环境变量的值,会被后面的RUN使用 |
ADD 源文件/目录 目标文件/目录 | 将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中,或者是一个URL |
COPY 源文件/目录 目标文件/目录 | 将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中 |
VOLUME [“目录”] | 在容器中创建一个挂载点 |
USER 用户名/UID | 指定运行容器时的用户 |
WORKDIR 路径 | 为后续的RUN、CMD、ENTRYPOINT指定工作目录 |
ONBUILD 命令 | 指定所生成的镜像作为一个基础镜像时所要运行的命令 |
HEALTHCHECK | 健康检查 |
其中ADD是将宿主系统的某个文件复制到容器的某个路径下,VOLUME是将宿主系统的一个目录共享出来,让容器挂载,使用目录中的文件。
[root@localhost ~]# cd /opt
[root@localhost opt]# mkdir apache
[root@localhost opt]# cd apache/
[root@localhost apache]# vim Dockerfile
基于基础镜像
FROM centos:7
维护镜像的用户信息,MAINTAINER后面随便自己写点啥
MAINTAINER Hello World
镜像操作指令安装apache软件
RUN yum -y update
RUN yum -y install httpd
开启80端口
EXPOSE 80
复制网站首页文件
ADD index.html /var/www/html
将执行加脚本复制到镜像中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
启动容器时执行脚本
CMD ["/run.sh"]
在当前目录下编辑网站首页、执行脚本,命名严格按照Dockerfile中的命名。
[root@localhost apache]# vim index.html
<h1>this is a web</h1>
[root@localhost apache]# vim run.sh
#!bin/bash
rm -rf /run/httpd/* ##清空apache缓存,比如apache的pid文件等
exec /usr/sbin/apachectl -D FOREGROUND ##启动apache服务
最后开始生成镜像,生成镜像会按照Dockerfile文件中写的9个步骤依次执行,每一步都会创建一个新的容器,执行完成后会自动释放,每一步执行完成会生成一个层的ID号,最后生成的就是镜像ID。
[root@localhost apache]# docker build -t httpd:centos . ##生成镜像
[root@localhost apache]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd centos b4d58c9f069e 20 minutes ago 419MB
gouzhen new bfb7a549a00d 11 hours ago 215MB
gouzhen test e956e4a130fb 12 hours ago 203MB
centos 7 7e6257c9f8d8 5 weeks ago 203MB
[root@localhost apache]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed09c91fef90 centos:7 "/bin/bash" 13 hours ago Up 13 hours vigorous_kepler
[root@localhost apache]# docker run -d -p 80:80 httpd:centos ##将服务在镜像中跑起来,-d表示守护进程开启,-p表示指定端口进行映射,-P表示随机端口进行映射
fbf0ee25689ae7b9ecabb165e703bad34e669beecf4eaa262522a605360e772a
[root@localhost apache]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fbf0ee25689a httpd:centos "/run.sh" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp jolly_lichterman
ed09c91fef90 centos:7 "/bin/bash" 13 hours ago Up 13 hours vigorous_kepler
1.3.2 基于已有的镜像容器进行创建镜像
基于已有的镜像容器进行创建镜像需要用到docker commit命令
OPTIONS | 说明 |
-a | 提交的镜像作者 |
-c | 使用Dockerfile指令来创建镜像 |
-m | 提交时的说明文字 |
-p | 在commit时,将容器暂停(默认为true) |
[root@localhost ~]# docker pull centos:7 ##下载centos7的镜像
[root@localhost ~]# docker images ##查看镜像列表
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 7e6257c9f8d8 5 weeks ago 203MB
[root@localhost ~]# docker create -it centos:7 /bin/bash ##创建centos7的容器
ed09c91fef901d43fd167493161e9d863fb98128f567ebf04b8890c2e4dfa13a
[root@localhost ~]# docker ps -a ##查看容器列表
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed09c91fef90 centos:7 "/bin/bash" About a minute ago Created vigorous_kepler
[root@localhost ~]# docker start ed09c91fef90 ##开启centos7的容器
ed09c91fef90
创建镜像
[root@localhost ~]# docker commit -m "new" -a "gouzhen" ed09c91fef90 gouzhen:test ##通过已有镜像容器创建镜像
sha256:e956e4a130fb77293e07c6c36220183cced69f97572e711a3a0ca4ac63174698
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed09c91fef90 centos:7 "/bin/bash" 53 minutes ago Up 51 minutes vigorous_kepler
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gouzhen test e956e4a130fb 28 seconds ago 203MB
centos 7 7e6257c9f8d8 5 weeks ago 203MB
1.3.3 基于本地模板进行构建
- 下载本地模板
通过导入系统模板文件可以生成镜像,模板可以从OPENVZ开源项目下载
地址为:https://wiki.openvz.org/Download/template/precreated
或者使用wget下载:wget
http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
- 模板下载后直接导入即可
[root@localhost ~]# cd /opt
将下载的模板拷贝过来
[root@localhost opt]# ls
debian-7.0-x86-minimal.tar.gz
[root@localhost opt]# cat debian-7.0-x86-minimal.tar.gz | docker import - gouzhen:new ##基于模板创建镜像
sha256:bfb7a549a00d15e357dd4deb793728b3fec58f443daedd9c014529f2e0cf32d6
[root@localhost opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gouzhen new bfb7a549a00d 6 seconds ago 215MB
gouzhen test e956e4a130fb 13 minutes ago 203MB
centos 7 7e6257c9f8d8 5 weeks ago 203MB
二、 docker的数据管理
2.1 数据卷
容器和宿主机之间的资源共享
[root@localhost apache]# docker run -v /var/www:/data1 --name web1 -it centos:7 /bin/bash ##将宿主机的/var/www目录共享出去给容器的/data1,-v表示volume卷
在执行命令之前是没有/var/www这个目录,使用以上命令进了容器中
[root@b0e3133b917c /]# ls ##同时也创建了/data1目录
anaconda-post.log data1 etc lib media opt root sbin sys usr
bin dev home lib64 mnt proc run srv tmp var
[root@b0e3133b917c /]# cd data1/
[root@b0e3133b917c data1]# ls
[root@b0e3133b917c data1]# touch 123 ##在这里创建一个文件123
重新打开一个终端查看/var/www上是否同步了这个文件
[root@localhost ~]# cd /var/www/
[root@localhost www]# ls
123
同时在宿主机上写一个456文件
[root@localhost www]# touch 456
在容器中查看
[root@b0e3133b917c data1]# ls
123 456
2.2 数据卷容器
容器与容器之间的资源共享
[root@localhost ~]# docker run --name web100 -v /data1 -v data2 -it centos:7 /bin/bash ##创建数据卷容器
[root@7db720707b00 /]# ls
anaconda-post.log data1 dev home lib64 mnt proc run srv tmp var
bin data2 etc lib media opt root sbin sys usr
重新打开一个终端,创建一个新容器,新容器挂载数据卷容器web100
[root@localhost ~]# docker run -it --volumes-from web100 --name web99 centos:7 /bin/bash ##创建新容器挂载数据卷容器web100
[root@3221dccf3b99 /]# ls
anaconda-post.log data1 dev home lib64 mnt proc run srv tmp var
bin data2 etc lib media opt root sbin sys usr
分别在两个容器的data1和data2目录下创建文件,并互相查看(注意容器id)
[root@7db720707b00 /]# cd data1
[root@7db720707b00 data1]# touch qqq
[root@7db720707b00 data1]# cd ../data2
[root@7db720707b00 /]# cd data2
[root@7db720707b00 data2]# ls
www
[root@3221dccf3b99 /]# cd data2
[root@3221dccf3b99 data2]# touch www
[root@3221dccf3b99 data2]# cd ../data1
[root@3221dccf3b99 data1]# ls
qqq
三、 搭建私有仓库
3.1 搭建仓库
registry是镜像和图表的仓库。registry的端口是5000。
[root@localhost ~]# docker pull registry ##下载registry的镜像
Using default tag: latest
latest: Pulling from library/registry
cbdbe7a5bc2a: Pull complete
47112e65547d: Pull complete
46bcb632e506: Pull complete
c1cc712bcecd: Pull complete
3db6272dcbfa: Pull complete
Digest: sha256:8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest
[root@localhost ~]# vim /etc/docker/daemon.json
"insecure-registries":["14.0.0.110:5000"], ##添加这一条信息,说明私有仓库的位置
[root@localhost ~]# systemctl restart docker.service ##重启docker服务
创建容器
[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry ##宿主机的/data/registry自动创建挂载容器中的/tmp/registry
c63ad00df00713c375f7708642ec0000166551b6c13d0b494eef34bfaddddde4
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c63ad00df007 registry "/entrypoint.sh /etc…" 14 seconds ago Up 12 seconds 0.0.0.0:5000->5000/tcp hungry_lalande
3.2 上传、下载私有仓库中的镜像
拉取一个nginx的镜像,进行私有镜像仓库上传
[root@localhost ~]# docker pull nginx ##拉取nginx镜像
[root@localhost ~]# docker tag nginx:latest 14.0.0.110:5000/nginx ##将刚刚拉取得nginx镜像改一个标签,明明严格按照"仓库的IP地址:端口/镜像名称"的方式书写
[root@localhost ~]# docker push 14.0.0.110:5000/nginx ##上传镜像
The push refers to repository [14.0.0.110:5000/nginx]
908cf8238301: Pushed
eabfa4cd2d12: Pushed
60c688e8765e: Pushed
f431d0917d41: Pushed
07cab4339852: Pushed
latest: digest: sha256:794275d96b4ab96eeb954728a7bf11156570e8372ecd5ed0cbc7280313a27d19 size: 1362
[root@localhost ~]# curl -XGET http://14.0.0.110:5000/v2/_catalog ##查看私有仓库镜像列表
{"repositories":["nginx"]}
下载私有仓库的nginx镜像
先删除原有的nginx镜像
[root@localhost ~]# docker rmi 14.0.0.110:5000/nginx:latest
[root@localhost ~]# docker rmi nginx:latest
查看现有的镜像列表
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd centos b4d58c9f069e 13 hours ago 419MB
centos 7 7e6257c9f8d8 5 weeks ago 203MB
registry latest 2d4f4b5309b1 3 months ago 26.2MB
下载私有仓库的镜像
[root@localhost ~]# docker pull 14.0.0.110:5000/nginx
Using default tag: latest
latest: Pulling from nginx
d121f8d1c412: Pull complete
ebd81fc8c071: Pull complete
655316c160af: Pull complete
d15953c0e0f8: Pull complete
2ee525c5c3cc: Pull complete
Digest: sha256:794275d96b4ab96eeb954728a7bf11156570e8372ecd5ed0cbc7280313a27d19
Status: Downloaded newer image for 14.0.0.110:5000/nginx:latest
14.0.0.110:5000/nginx:latest
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd centos b4d58c9f069e 13 hours ago 419MB
gouzhen new bfb7a549a00d 24 hours ago 215MB
gouzhen test e956e4a130fb 24 hours ago 203MB
14.0.0.110:5000/nginx latest 7e4d58f0e5f3 11 days ago 133MB
centos 7 7e6257c9f8d8 5 weeks ago 203MB
registry latest 2d4f4b5309b1 3 months ago 26.2MB
四、 容器间通信
4.1 实现容器之间的通信
创建并运行Hello容器,端口号自动映射
[root@localhost ~]# docker run -itd -P --name Hello centos:7 /bin/bash
9432b9f5a78ee0cbf74c4feb00623f2bbbd0b315f910f397c04269dda81b6817
创建并运行World容器,连接到Hello和其通信,端口号自动映射
[root@localhost ~]# docker run -itd -P --name World --link Hello:Everyday centos:7 /bin/bash
3e1747515e4bf3f5bdb8d651d32469ccd0e78cc1dc005c60b48d486655bcf8d9
测试,进入Hello,ping World
[root@localhost ~]# docker exec -it 3e1747515e4bf /bin/bash
[root@3e1747515e4b /]# ping World
ping: World: Name or service not known
[root@3e1747515e4b /]# ping Hello
PING Everyday (172.17.0.3) 56(84) bytes of data.
64 bytes from Everyday (172.17.0.3): icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from Everyday (172.17.0.3): icmp_seq=2 ttl=64 time=0.096 ms
^C
--- Everyday ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.077/0.086/0.096/0.013 ms
[root@3e1747515e4b /]# yum install net-tools -y
这时候,只有World能ping通Hello,两个容器并不能互通,想要实现互通,需要通过中转网卡连接。
4.2 通过中转网卡连接,实现互通(注:只能用于最新版本的centos)
默认网络中的link是静态的,不允许链接容器重启,而自定义网络下的link是动态的,支持链接容器重启(以及IP变化)。因此,使用link时链接的容器,在默认网络中必须提前创建好,而自定义网络下不必预先建好。使用网络别名后,不管容器ip地址如何变化,都可以根据别名进行连接。而且这种方式可以使得多个容器互联。
[root@localhost ~]# docker network create newcard ##创建一个新的网卡,网卡名称可以自己命名
1776b94673d0b7912feadff01d6b7a54a731ecbe41eb5f4b37e6dabdf02bede1
[root@localhost ~]# ifconfig ##查看网卡信息
br-1776b94673d0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:f6:a9:2c:f4 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- –network newcard表示使用mynet网络
- –network-alias 123表示该容器运行时,使用的网络别名为123。(网络别名的作用类似hostname,不管容器IP如何变化,都可以使用同一个别名)。
- –name 表示此容器的别名
- -itd 表示后台运行 打开一个虚拟终端 打开标准型输入
基于centos:7镜像和新的网卡创建多个容器
[root@localhost ~]# docker run -itd --name abc --network newcard --network-alias abc centos /bin/bash
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
3c72a8ed6814: Pull complete
Digest: sha256:76d24f3ba3317fa945743bb3746fbaf3a0b752f10b10376960de01da70685fbd
Status: Downloaded newer image for centos:latest
64d6fb1191f90adce3552d4af58161838616b0f646d33a2e541ed87e21bd6bc3
[root@localhost ~]# docker run -itd --name def --network newcard --network-alias def centos /bin/bash
cc4df8da632234c656f83b0b7911156045b62c14f489f906be123b99daa71f0f
分别进入容器进行ping测试
[root@localhost ~]# docker exec -it abc /bin/bash
[root@64d6fb1191f9 /]# ping 456
connect: Invalid argument
[root@64d6fb1191f9 /]# ping def
PING def (172.18.0.5) 56(84) bytes of data.
64 bytes from def.newcard (172.18.0.5): icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from def.newcard (172.18.0.5): icmp_seq=2 ttl=64 time=0.058 ms
^C
--- def ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1ms
rtt min/avg/max/mdev = 0.051/0.054/0.058/0.008 ms
[root@64d6fb1191f9 /]# exit
exit
[root@localhost ~]# docker exec -it def /bin/bash
[root@cc4df8da6322 /]# ping abc
PING abc (172.18.0.4) 56(84) bytes of data.
64 bytes from abc.newcard (172.18.0.4): icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from abc.newcard (172.18.0.4): icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from abc.newcard (172.18.0.4): icmp_seq=3 ttl=64 time=0.058 ms
^C
--- abc ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.025/0.074/0.139/0.047 ms