Dockerfile自定义镜像
1) Dockerfile介绍
Dockerfile 是自动构建 docker镜像的配置文件, 用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于linux 下的 shell 命令。
我们可以通过下面这幅图来直观地感受下 Docker 镜像、容器和 Dockerfile 三者之间的关系。
我们从上图中可以看到, Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。
2) Dockerfile的基本结构
Dockerfile 是由一行行命令语句组成,并且支持已 # 开头的注释行。
一般来说,我们可以将 Dockerfile 分为四个部分:
基础镜像(父镜像)信息指令 FROM
维护者信息指令 MAINTAINER
镜像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等
容器启动指令 CMD 、ENTRYPOINT 和 USER 等
3)使用 Dockerfile 定制镜像/自定义镜像
Q
为什么要自定义Docker镜像?
A
工作中Docker中的镜像并不满足工作的需要,需要进行自己的配置。
Docker Hub 中 99% 的镜像都是通过在base 镜像中安装和配置需要的软件构建出来的
4) 使用 Docker build 构建镜像创建容器的步骤
第一步 编写Dockerfile文件
第二步 Docker build
第三步 Docker run
4-1 企业案例通过Dockerfile自定义Centos镜像
docker pull centos
官方镜像 docker run -i -t
官方进行我们执行的命令不支持,显然是不符合我们需求的
【注意】现在我们需要自定义一个镜像来支持 VIM、ifconfig、并且登录后的默认路径改做修改。
企业级案例
一、拉一个基础centos镜像
docker pull centos
二、编写dockerfile文件
vim Dockerfile
#从哪一个基础镜像构建
FROM centos
#定义作者的信息
MAINTAINER 1907
#定义一个变量
ENV newpath /tmp
#设置登录以后工作路径(落脚点)
WORKDIR $newpath
#干了什么(执行你要的操作)
RUN yum install -y vim
RUN yum install -y net-tools
##如果有更多的需求 。。。RUN
#开放指定的端口
EXPOSE 80
EXPOSE 22
#执行命令
CMD echo $newpath
CMD echo "success ok"
CMD /bin/bash
~
三、通过dockerfile文件创建镜像
[root@localhost home]# docker build -f Dockerfile -t azkaban/custom_centos:v1 .
Sending build context to Docker daemon 5.632kB
Step 1/11 : FROM centos
---> 470671670cac
Step 2/11 : MAINTAINER 1907
---> Running in d24bf9043207
Removing intermediate container d24bf9043207
---> 159ad59927d2
Step 3/11 : ENV newpath /tmp
---> Running in 5fa9a2ebc28c
Removing intermediate container 5fa9a2ebc28c
---> c6bec0ee09b9
Step 4/11 : WORKDIR $newpath
---> Running in ab29e7e49eda
Removing intermediate container ab29e7e49eda
---> f79d02d81a18
Step 5/11 : RUN yum install -y vim
---> Running in 9474c83bfe6c
CentOS-8 - AppStream 342 kB/s | 6.4 MB 00:19
CentOS-8 - Base 113 kB/s | 5.0 MB 00:44
CentOS-8 - Extras 1.9 kB/s | 2.1 kB 00:01
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
vim-enhanced x86_64 2:8.0.1763-13.el8 AppStream 1.4 M
Installing dependencies:
gpm-libs x86_64 1.20.7-15.el8 AppStream 39 k
vim-common x86_64 2:8.0.1763-13.el8 AppStream 6.3 M
vim-filesystem noarch 2:8.0.1763-13.el8 AppStream 48 k
which x86_64 2.21-10.el8 BaseOS 49 k
Transaction Summary
================================================================================
Install 5 Packages
Total download size: 7.8 M
Installed size: 31 M
Downloading Packages:
(1/5): gpm-libs-1.20.7-15.el8.x86_64.rpm 50 kB/s | 39 kB 00:00
(2/5): vim-filesystem-8.0.1763-13.el8.noarch.rp 239 kB/s | 48 kB 00:00
(3/5): which-2.21-10.el8.x86_64.rpm 121 kB/s | 49 kB 00:00
(4/5): vim-common-8.0.1763-13.el8.x86_64.rpm 573 kB/s | 6.3 MB 00:11
[MIRROR] vim-enhanced-8.0.1763-13.el8.x86_64.rpm: Curl error (28): Timeout was reached for http://mirrors.ustc.edu.cn/centos/8.1.1911/AppStream/x86_64/os/Packages/vim-enhanced-8.0.1763-13.el8.x86_64.rpm [Operation too slow. Less than 1000 bytes/sec transferred the last 30 seconds]
(5/5): vim-enhanced-8.0.1763-13.el8.x86_64.rpm 44 kB/s | 1.4 MB 00:31
--------------------------------------------------------------------------------
Total 208 kB/s | 7.8 MB 00:38
warning: /var/cache/dnf/AppStream-02e86d1c976ab532/packages/gpm-libs-1.20.7-15.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS-8 - AppStream 1.6 MB/s | 1.6 kB 00:00
Importing GPG key 0x8483C65D:
Userid : "CentOS (CentOS Official Signing Key) "
Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : which-2.21-10.el8.x86_64 1/5
Installing : vim-filesystem-2:8.0.1763-13.el8.noarch 2/5
Installing : vim-common-2:8.0.1763-13.el8.x86_64 3/5
Installing : gpm-libs-1.20.7-15.el8.x86_64 4/5
Running scriptlet: gpm-libs-1.20.7-15.el8.x86_64 4/5
Installing : vim-enhanced-2:8.0.1763-13.el8.x86_64 5/5
Running scriptlet: vim-enhanced-2:8.0.1763-13.el8.x86_64 5/5
Running scriptlet: vim-common-2:8.0.1763-13.el8.x86_64 5/5
Verifying : gpm-libs-1.20.7-15.el8.x86_64 1/5
Verifying : vim-common-2:8.0.1763-13.el8.x86_64 2/5
Verifying : vim-enhanced-2:8.0.1763-13.el8.x86_64 3/5
Verifying : vim-filesystem-2:8.0.1763-13.el8.noarch 4/5
Verifying : which-2.21-10.el8.x86_64 5/5
Installed:
vim-enhanced-2:8.0.1763-13.el8.x86_64 gpm-libs-1.20.7-15.el8.x86_64
vim-common-2:8.0.1763-13.el8.x86_64 vim-filesystem-2:8.0.1763-13.el8.noarch
which-2.21-10.el8.x86_64
Complete!
Removing intermediate container 9474c83bfe6c
---> d1773a676980
Step 6/11 : RUN yum install -y net-tools
---> Running in c28e68f52b0e
Last metadata expiration check: 0:00:47 ago on Sun Feb 23 01:59:52 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
net-tools x86_64 2.0-0.51.20160912git.el8 BaseOS 323 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 323 k
Installed size: 1.0 M
Downloading Packages:
net-tools-2.0-0.51.20160912git.el8.x86_64.rpm 1.1 MB/s | 323 kB 00:00
--------------------------------------------------------------------------------
Total 112 kB/s | 323 kB 00:02
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Running scriptlet: net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Verifying : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Installed:
net-tools-2.0-0.51.20160912git.el8.x86_64
Complete!
Removing intermediate container c28e68f52b0e
---> 9de3592d6946
Step 7/11 : EXPOSE 80
---> Running in 5569cdc7691d
Removing intermediate container 5569cdc7691d
---> 3a16923f249c
Step 8/11 : EXPOSE 22
---> Running in 272964d43403
Removing intermediate container 272964d43403
---> 66a7ac68030b
Step 9/11 : CMD echo $newpath
---> Running in 86d6d8655e4b
Removing intermediate container 86d6d8655e4b
---> bb617cf4c488
Step 10/11 : CMD echo "success ok"
---> Running in 876412b8e523
Removing intermediate container 876412b8e523
---> 96915955be0c
Step 11/11 : CMD /bin/bash
---> Running in 809bd856d4fa
Removing intermediate container 809bd856d4fa
---> 2ba838e1b3ae
Successfully built 2ba838e1b3ae
Successfully tagged azkaban/custom_centos:v1
自己构建的镜像成功 docker images查看
四 通过Docker run 创建容器,,验证vim 以及net-tools
通过我们自定义的镜像创建容器
测试ifconfig命令 OK
测试vim 命令OK
看看构建过程是否是如前面所说,这也证实了镜像的分层
4)Dockerfile镜像分层
dockerfile中的每一条命令,都会构建一层文件。
以下图的Dockerfile为例分析构建过程
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
只有容器层是可写的,容器层下面的所有镜像层都是只读的。
下面我们深入讨论容器层的细节。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
1.添加文件
在容器中创建文件时,新文件被添加到容器层中。
读取文件
在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
修改文件
在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
删除文件
在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
5) Dockerfile指令详解
一张图搞定Dockerfile常见命令
Dockerfile中包括FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD等13个指令。
FROM
格式为FROM image或FROM image:tag,并且Dockerfile中第一条指令必须是FROM指令,且在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令。
MAINTAINER
格式为MAINTAINER user_name user_email,指定维护者信息
RUN
格式为RUN command或 RUN ["EXECUTABLE","PARAM1","PARAM2".....],前者在shell终端中运行命令,/bin/sh -c command,例如:/bin/sh -c "echo hello";后者使用exec执行,指定其他运行终端使用RUN["/bin/bash","-c","echo hello"]
每条RUN指令将当前的镜像基础上执行指令,并提交为新的镜像,命令较长的时候可以使用\来换行。
CMD
支持三种格式:
CMD ["executable","param1","param2"],使用exec执行,这是推荐的方式。
CMD command param1 param2 在/bin/sh中执行。
CMD ["param1","param2"] 提供给ENTERYPOINT的默认参数。
CMD用于指定容器启动时执行的命令,每个Dockerfile只能有一个CMD命令,多个CMD命令只执行最后一个。若容器启动时指定了运行的命令,则会覆盖掉CMD中指定的命令。
EXPOSE
格式为 EXPOSE port [port2,port3,...],例如EXPOSE 80这条指令告诉Docker服务器暴露80端口,供容器外部连接使用。
在启动容器的使用使用-P,Docker会自动分配一个端口和转发指定的端口,使用-p可以具体指定使用哪个本地的端口来映射对外开放的端口。
ENV
格式为:EVN key value 。用于指定环境变量,这些环境变量,后续可以被RUN指令使用,容器运行起来之后,也可以在容器中获取这些环境变量。
例如
ENV word hello
RUN echo $word
ADD
格式:ADD src dest
该命令将复制指定本地目录中的文件到容器中的dest中,src可以是一个绝对路径,也可以是一个URL或一个tar文件,tar文件会自动解压为目录。
COPY
格式为:COPY src desc
复制本地主机src目录或文件到容器的desc目录,desc不存在时会自动创建。
ENTRYPOINT
格式有两种:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1,param2 会在shell中执行。
用于配置容器启动后执行的命令,这些命令不能被docker run提供的参数覆盖。和CMD一样,每个Dockerfile中只能有一个ENTRYPOINT,当有多个时最后一个生效。
VOLUME
格式为 VOLUME ["/data"]
作用是创建在本地主机或其他容器可以挂载的数据卷,用来存放数据。
USER
格式为:USER username
指定容器运行时的用户名或UID,后续的RUN也会使用指定的用户。要临时使用管理员权限可以使用sudo。在USER命令之前可以使用RUN命令创建需要的用户。
例如:RUN groupadd -r docker && useradd -r -g docker docker
WORKDIR
格式: WORKDIR /path
为后续的RUN CMD ENTRYPOINT指定配置工作目录,可以使用多个WORKDIR指令,若后续指令用得是相对路径,则会基于之前的命令指定路径。
ONBUILD
格式ONBUILD [INSTRUCTION]
该配置指定当所创建的镜像作为其他新建镜像的基础镜像时所执行的指令。
例如下面的Dockerfile创建了镜像A:
ONBUILD ADD . /app
ONBUILD RUN python app.py
则基于镜像A创建新的镜像时,新的Dockerfile中使用from A 指定基镜像时,自动执行ONBBUILD指令内容,等价于在新的要构建镜像的Dockerfile中增加了两条指令:
FROM A
ADD ./app
RUN python app.py
docker build
创建好Dockerfile之后,通过docker build命令来创建镜像,该命令首先会上传Dockerfile文件给Docker服务器端,服务器端将逐行执行Dockerfile中定义的指令。
通常建议放置Dockerfile的目录为空目录。另外可以在目录下创建.dockerignore文件,让Docker忽略路径下的文件和目录,这一点与Git中的配置很相似。
通过 -t 指定镜像的标签信息,例如:docker build -t regenzm/first_image . ## "."指定的是Dockerfile所在的路径
例:
简单 使用 Dockerfile文件事例