Docker镜像的构建方式

摘要

在构建容器化应用时,相当重要的步骤莫过于镜像制作,本文将介绍镜像制作方法以及镜像制作的建议。
采用docker commit生成的镜像实际上是容器内的文件系统进行修改在进行提交,而运行的容器实际上是在镜像的文件系统顶层添加了一层读写层,所都的修改都是基于这一层,当生成镜像时会将这一层数据保存,所以每次使用commit提交镜像时候都会比原来多一层,这样会使得镜像越来越大并且不易维护。同时,对于镜像使用者来说完全不透明,使用者不清楚该镜像怎么样构建的,是否安全等,这种方式及其不推荐。
而使用Dockerfile构建镜像,对于使用者来说完全透明,构建镜像的每一个步骤都在Dockerfile文件中描述的清清楚楚,同时当需要对镜像修改时候,只需修改Dockerfile文件中的指令,维护镜像只需要维护一个Dockerfile,这也是镜像构建的最佳方式。当然,要使用Dockerfile就必须明白Dockerfile的语法和各个指令,以下将作详细介绍。

一、Docker镜像的分层

镜像

Dockerfile生成

每层运行一个容器,运行完成后移除

CMD[“./run.sh”]

Json

VOLUME /date

Json

ADD run.sh /

/run.sh

FROM centos:7

 

  • Dockerfile中的每个指令都会创建一个新的镜像层
  • 镜像层将被缓存和复用
  • 当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
  • 某一层的镜像缓存失效之后,它之后的镜像层都会失效
  • 镜像层时不可变的,如果在某一层中添加一个文件,然后再下一层中删除它,则镜像中依然会包含该文件

二、Docker镜像的创建

2.1、Docker镜像

2.1.1、应用发布的标准格式

2.1.2、支撑一个Docker容器的运行

2.2、Docker镜像的创建方法

2.2.1、基于已有镜像创建

2.2.2、基于本地模板创建

2.2.3、基于Dockerfile创建

2.3、基于已有镜像创建

2.3.1、将容器里面运行的程序及运行环境打包生成新的镜像

1 docker commit [选项] 容器ID/名称 仓库名称:[标签]
2 -m:说明信息
3 -a:作者信息
4 -p:生成过程中停止容器的运行

2.3.2、操作步骤

1 [root@server1 ~]# docker commit -m "new" -a "xu" 1495c44b9eb9 httpd:xin
2 sha256:9205c504d1886ab44f97ddc54edeef3c38b135d11cf2a8ed63bcb7a7b551a34b
3 [root@server1 ~]# docker images
4 REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
5 httpd               xin                 9205c504d188        7 seconds ago  

2.4、基于本地模板创建

1 导入本地镜像debian-7.0-x86-minimal.tar.gz
2 [root@server1 ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - docker:debian
3 sha256:91d49f99a942cf4737dadc1d4e25e738eeb94e2aa7d10b01e06ceb56b9f4926a
4 [root@server1 ~]# docker images
5 REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
6 docker              debian              91d49f99a942        9 seconds ago       215MB

2.5、基于Dockerfile创建

2.5.1、Dockerfile是由一组指令组成的文件

2.5.2、Dockerfile结构四部分

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

2.5.3、Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#”号开头的注释

2.5.4、Dockerfile操作指令

指令

含义

FROM 镜像

指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令

MAINTAINER 名字

说明新镜像的维护人信息

RUN 命令

在所基于的镜像上执行命令,并提交到新的镜像中

CMD [“要运行的程序”,“参数”]

指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能最后一条被执行

EXPOSE 端口号

指定新镜像加载到Docker时要开启的端口

ENV 环境变量 变量值

设置一个环境变量的值,会被后面的RUN使用

ADD 源文件/目录 目标文件/目录

将主机的文件拷贝到容器中,源文件要与Dockerfile位于相同目录中,或者是一个URL,自动进行解压操作,不需要手动解压

COPY 源文件/目录 目标文件/目录

将容器中的文件拷贝到容器的其他目录中

VOLUME [“目录”]

再容器中创建一个挂载点

USER 用户名/UID

指定运行容器时的用户

WORKDIR 路径

为后续的RUN、CMD、ENTRYPOINT指定工作目录

ONBUILD 命令

指定所生成的镜像作为一个基础镜像时所要运行的命令

HEALTHCHECK

健康检查

2.5.5、Dockerfile创建

 1 [root@server1 httpd]# mkdir httpd
 2 [root@server1 httpd]# cd httpd
 3 [root@server1 httpd]# vim Dockerfile
 4 #基于centos:7的基础镜像
 5 FROM centos:7
 6 #维护镜像的用户信息
 7 MAINTAINER this is project
 8 #镜像操作指令安装apache软件
10 RUN yum -y install httpd 11 #开启80端口 12 EXPOSE 80 13 #复制网址首页文件 14 ADD index.html /var/www/html/index.html 15 #将执行脚本复制到镜像中 16 ADD run.sh /run.sh 17 RUN chmod 755 /run.sh 18 #启动容器时执行脚本 19 CMD ["/run.sh"]

2.5.6、制作脚本

1 [root@server1 httpd]# vim run.sh
2 #!/bin/bash
3 rm -rf /run/httpd/*
4 exec /usr/sbin/apachectl -D FOREGROUND

2.5.7、制作网页

1 [root@server1 httpd]# echo '<h1>this is web</h1>' > index.html 
2 [root@server1 httpd]# ll      #文件要放同一个目录
3 总用量 12
4 -rw-r--r--. 1 root root 402 11月 26 15:13 Dockerfile
5 -rw-r--r--. 1 root root  21 11月 26 15:16 index.html
6 -rw-r--r--. 1 root root  71 11月 26 15:15 run.sh

 2.5.8、生成镜像

 1 [root@server1 httpd]# docker build -t httpd:centos .
 2 Sending build context to Docker daemon  4.096kB
 3 Step 1/9 : FROM centos:7
 4 7: Pulling from library/centos
 5 2d473b07cdd5: Pull complete 
 6 Digest: sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e
 7 Status: Downloaded newer image for centos:7
 8  ---> 8652b9f0cb4c
 9 Step 2/9 : MAINTAINER this is project
10  ---> Running in 6ef16daecd7f      #每次执行都会运行一个容器,运行后移除
11 Removing intermediate container 6ef16daecd7f
12  ---> a7a48005092b
13 Step 3/9 : RUN yum -y install update
14  ---> Running in 7b105c9b4747

2.5.9、新镜像运行容器

1 [root@server1 httpd]# docker run -d -p 2222:80 httpd:centos 
2 d87c48f281e888254d6a74cf781fccf80c18feab78103b2a1d3726fe9bb9aae5
3 [root@server1 httpd]# docker ps -a 
4 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                  NAMES
5 d87c48f281e8        httpd:centos        "/run.sh"                6 seconds ago       Up 5 seconds               0.0.0.0:2222->80/tcp   sleepy_shannon

2.5.10、测试

三、私有仓库建立

3.1、拉取镜像及修改配置文件(端口号:5000)

 1 #拉取镜像
 2 [root@server1 httpd]# docker pull registry
 3 Using default tag: latest
 4 latest: Pulling from library/registry
 5 cbdbe7a5bc2a: Pull complete 
 6 47112e65547d: Pull complete 
 7 46bcb632e506: Pull complete 
 8 c1cc712bcecd: Pull complete 
 9 3db6272dcbfa: Pull complete 
10 Digest: sha256:8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d
11 Status: Downloaded newer image for registry:latest
12 docker.io/library/registry:latest
13 
14 修改配置文件
15 [root@server1 httpd]# vim /etc/docker/daemon.json 
16 {
17 "insecure-registries": ["20.0.0.10:5000"],       #添加
18 "registry-mirrors": ["https://lyoy0ey2.mirror.aliyuncs.com"]
19 }
20 
21 重启服务
22 [root@server1 httpd]# systemctl restart docker.service 

3.2、创建镜像并查看

1 [root@server1 httpd]# docker create -it registry /bin/bash
2 b8fca969d55da2cd78b07750142498eda2ffe25428edbff1aa592fb4f08c20ed
3 
4 [root@server1 httpd]# docker ps -a 
5 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                            PORTS               NAMES
6 b8fca969d55d        registry            "/entrypoint.sh /bin…"   6 seconds ago       Created                                               fervent_noether
7 
8 [root@server1 httpd]# docker start b8fca969d55d 
9 b8fca969d55d

3.3、宿主机的/data/registry自动创建挂载容器中的/tmp/registry

1 [root@server1 httpd]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
2 de58e178a3172ecc8c52bcaf4063da21a5eb9a1605180add6a03a8064a257cf5
3 [root@server1 httpd]# docker tag httpd:centos 20.0.0.10:5000/httpd    #打标签

3.4、上传并获取

 1 上传
 2 [root@server1 httpd]# docker push 20.0.0.10:5000/httpd
 3 The push refers to repository [20.0.0.10:5000/httpd]
 4 7bf28fb5dbac: Pushed 
 5 35fc0f295312: Pushed 
 6 3069654c482f: Pushed 
 7 5eb6c74f0823: Pushed 
 8 174f56854903: Pushed 
 9 latest: digest: sha256:1782102d1c3c1231cd4c17035381e83dc2844547af30c9067a3f96334d585dba size: 1362
10 
11 获取私有仓库列表
12 [root@server1 httpd]# curl -XGET http://20.0.0.10:5000/v2/_catalog
13 {"repositories":["httpd"]}    #显示上传成功
14 
15 删除centos镜像
16 [root@server1 registry]# docker rmi 20.0.0.10:5000/httpd:latest 
17 
18 测试私有仓库下载
19 [root@server1 registry]# docker pull 20.0.0.10:5000/httpd
20 Using default tag: latest
21 latest: Pulling from httpd
22 2d473b07cdd5: Already exists 
23 5e105bbe607b: Pull complete 
24 0ce1bb40a734: Pull complete 
25 bf8183ec3c05: Pull complete 
26 1b093a1fad54: Pull complete 
27 Digest: sha256:1782102d1c3c1231cd4c17035381e83dc2844547af30c9067a3f96334d585dba
28 Status: Downloaded newer image for 20.0.0.10:5000/httpd:latest
29 20.0.0.10:5000/httpd:latest

四、Docker数据卷管理

4.1、Docker数据卷

-v 会自动进行创建目录进行挂载(宿主机与容器之间挂载)

4.1.1、宿主机目录/var/www挂载容器中的/data1

1 [root@server1 registry]# docker run -v /var/www:/data1 --name web1 -it centos:7 /bin/bash      #运行完后进入容器
2 [root@6cfe7d1acca1 /]# cd /data1/
3 [root@6cfe7d1acca1 data1]# echo 'nihao!' > test.txt

4.1.2、宿主机查看

1 [root@server1 www]# cat /var/www/test.txt 
2 nihao!

4.2、数据卷容器

数据卷容器,新容器挂载数据卷容器web100(容器内部挂载)

 1 [root@server1 www]# docker run --name web100 -v /data2 -v /data3 -it centos:7 /bin/bash    #运行后进入容器
 2 
 3 再开一个主机
 4 [root@server1 registry]# docker run -it --volumes-from web100 --name db1 centos:7 /bin/bash
 5 
 6 查看
 7 [root@941d8414bc15 /]# ls
 8 anaconda-post.log  data3  home   media  proc  sbin  tmp
 9 bin                dev    lib    mnt    root  srv   usr
10 data2              etc    lib64  opt    run   sys   var
11 
12 [root@ac1a1deff23d /]# ls
13 anaconda-post.log  data3  home   media  proc  sbin  tmp
14 bin                dev    lib    mnt    root  srv   usr
15 data2              etc    lib64  opt    run   sys   var
16 
17 创建文件便查看
18 [root@ac1a1deff23d /]# cd data2
19 [root@ac1a1deff23d data2]# touch aa
20 [root@ac1a1deff23d data2]# ls
21 aa
22 [root@ac1a1deff23d data2]# cd /data3
23 [root@ac1a1deff23d data3]# touch bb
24 [root@ac1a1deff23d data3]# ls
25 bb
26 
27 [root@941d8414bc15 /]# cd data2
28 [root@941d8414bc15 data2]# ls
29 aa
30 [root@941d8414bc15 data2]# cd /data3
31 [root@941d8414bc15 data3]# ls
32 bb

4.3、端口映射

 1 [root@server1 httpd]# docker run -d -P httpd:centos            #P随机端口号,从32768开始
 2 8d2b86c97ac08628fb197d6fdbdabe883195fe43875f9e71efbca94ac559a0aa
 3 [root@server1 httpd]# docker ps -a
 4 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS                    NAMES
 5 8d2b86c97ac0        httpd:centos        "/run.sh"                5 seconds ago       Up 4 seconds                   0.0.0.0:32768->80/tcp    amazing_northcutt
 6 
 7 [root@server1 httpd]# docker run -d -p 2222:80 httpd:centos    #p指定端口号
 8 cc7230fdf9c3a40b05733f94989740f488aafdcb6648093325f84fb0fe0f460d
 9 [root@server1 httpd]# docker ps -a
10 CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                         PORTS                    NAMES
11 cc7230fdf9c3        httpd:centos        "/run.sh"                6 seconds ago        Up 5 seconds                   0.0.0.0:2222->80/tcp     heuristic_newton

4.4、容器互联

 1 创建并运行容器取名web11,端口号自动映射
 2 [root@server1 httpd]# docker run -dit -P --name web11 centos:7 /bin/bash
 3 5fa7635068c78b7c0fc331398ae5f4e393001c1f5c5f02072d11f3471f07e341
 4 
 5 --name 指定容器名称
 6 
 7 创建并运行容器取名web22
 8 [root@server1 httpd]# docker run -dit -P --name web22 --link web11:web11 centos:7 /bin/bash
 9 b413c6cbf148cb7670084e8e31c24993e61f1cc83efb2eee4a1cd38ee1325ed7
10 
11 --link 关联单向连接
12 
13 进web22容器ping web11
14 [root@server1 httpd]# docker ps -a
15 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                           PORTS                    NAMES
16 b413c6cbf148        centos:7            "/bin/bash"              3 minutes ago       Up 3 minutes                                              web22
17 5fa7635068c7        centos:7            "/bin/bash"              4 minutes ago       Up 4 minutes                                              web11
18 
19 [root@server1 httpd]# docker exec -it b413c6cbf148 /bin/bash
20 
21 [root@b413c6cbf148 /]# ping web11
22 PING web11 (172.17.0.5) 56(84) bytes of data.
23 64 bytes from web11 (172.17.0.5): icmp_seq=1 ttl=64 time=0.066 ms
24 64 bytes from web11 (172.17.0.5): icmp_seq=2 ttl=64 time=0.058 ms
25 64 bytes from web11 (172.17.0.5): icmp_seq=3 ttl=64 time=0.060 ms
26 --- web11 ping statistics ---
27 3 packets transmitted, 3 received, 0% packet loss, time 2000ms
28 rtt min/avg/max/mdev = 0.058/0.061/0.066/0.007 ms
29 
30 安装net工具
31 [root@b413c6cbf148 /]# yum -y install net-tools
32 [root@b413c6cbf148 /]# ifconfig     #查询网址信息
33 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
34         inet 172.17.0.6  netmask 255.255.0.0  broadcast 172.17.255.255     #第一个创建的容器地址是172.17.0.2,以此类推
35         ether 02:42:ac:11:00:06  txqueuelen 0  (Ethernet)
36         RX packets 7114  bytes 11320444 (10.7 MiB)
37         RX errors 0  dropped 0  overruns 0  frame 0
38         TX packets 3999  bytes 219299 (214.1 KiB)
39         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
40 
41 lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
42         inet 127.0.0.1  netmask 255.0.0.0
43         loop  txqueuelen 1  (Local Loopback)
44         RX packets 0  bytes 0 (0.0 B)
45         RX errors 0  dropped 0  overruns 0  frame 0
46         TX packets 0  bytes 0 (0.0 B)
47         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
原文地址:https://www.cnblogs.com/xuhao0705/p/14042469.html