简单来说,Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建的三个步骤:
这里以我们熟悉的Centos为例 ,查看DockerFile大致文件结构
FROM scratch
ADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20200114" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-01-14 00:00:00-08:00"
CMD ["/bin/bash"]
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会创建Docker容器,容器是直接提供服务的。
① Dockerfile内容基础知识
② Docker执行Dockerfile的大致流程
③ DockerFile体系结构(保留字指令)
FROM:基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER:镜像维护者的姓名和邮箱地址
RUN:容器构建时需要运行的命令
EXPOSE:当前容器对外暴露出的端口
WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV:用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,比如:WORKDIR $MY_PATH
ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY:类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径>
位置。实例如COPY src dest 或者 COPY ["src", "dest"]
VOLUME:容器数据卷,用于数据保存和持久化工作
CMD:指定一个容器启动时要运行的命令。Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。
ENTRYPOINT :指定一个容器启动时要运行的命令。ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。
ONBUILD:子镜像继承父镜像,子镜像运行时,父镜像ONBUILD被触发。
BUILD | BOTH | RUN |
---|---|---|
FROM | WORKDIR | CMD |
MAINTAINER | USER | ENV |
COPY | EXPOSE | |
ADD | VOLUME | |
RUN | ENTRYPOINT | |
ONBUILD |
④ ONBUILD测试
两个DockerFile文件:DockerFile3与DockerFile4。
DockerFile3内容如下:
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
ONBUILD RUN echo "now ,dockerfile3 is execute..."
生成镜像myip:
docker build -f DockerFile3 -t myip .
DockerFile4内容如下:
FROM myip
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
生成镜像myip4:
首先需要了解一个Base(scratch)镜像。Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
① 编写DockerFile文件
默认centos镜像是不支持登陆后的默认路径、 vim编辑器、查看网络配置ifconfig的,这里自定义DockerFile使其支持。
在自定义目录下创建DockerFile文件,如/mydocker/
下,内容如下:
##使用的时候注意去掉注释 可以在vim窗口模式下使用dd命令快速删除一行
#继承自centos镜像
FROM centos
#作者与邮箱
MAINTAINER jane<jane@qq.com>
#设置环境
ENV MYPATH /usr/local
#容器启动后的落脚路径
WORKDIR $MYPATH
#运行安装命令
RUN yum -y install vim
RUN yum -y install net-tools
#暴露80端口
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
② 构建生成镜像
在当前路径下/mydocker/执行如下格式命令:
docker build -f DockFile路径 -t 新镜像名字:TAG .
会看到 docker build 命令最后有一个 .
,其表示当前目录。
实例如下:
docker build -f DockerFile -t mycentos:2.0 .
[root@localhost mydocker]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mycentos 2.0 df8160eb077f About a minute ago 314.3 MB
jane/centos latest b3a32e0a2930 14 hours ago 237.1 MB
badtomcat 1.0 4c900ee6d6e3 19 hours ago 528.7 MB
tomcat latest dd7dc39599b6 37 hours ago 528.6 MB
centos latest 495a24dc98e8 3 weeks ago 237.1 MB
hello-world latest 9f5834b25059 13 months ago 1.84 kB
③ 创建容器并运行
命令格式如下:
docker run -it 新镜像名字:TAG [/bin/bash]
实例如下:
docker run -it df8160eb077f /bin/bash
④ 列出镜像的变更历史
命令格式如下:
docker history 镜像ID
二者相似之处都是都是指定一个容器启动时要运行的命令。
① CMD命令
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。
实例如下:
docker run -it -p 8888:8080 tomcat ls -l
那么DockerFile中的最后一个CMD会被ls -l
替换,如下图所示:
② ENTRYPOINT
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合。
③ CMD测试步骤
##新增DockerFile文件
[root@localhost mydocker]# vim DockerFile2
##build创建镜像
[root@localhost mydocker]# docker build -f DockerFile2 -t myip .
Sending build context to Docker daemon 4.096 kB
Sending build context to Docker daemon
Step 0 : FROM centos
---> 495a24dc98e8
Step 1 : RUN yum install -y curl
---> Running in 4fd0ea665eaf
CentOS-8 - AppStream 704 kB/s | 6.4 MB 00:09
CentOS-8 - Base 410 kB/s | 5.0 MB 00:12
CentOS-8 - Extras 2.2 kB/s | 2.1 kB 00:00
Package curl-7.61.1-11.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
---> 58218afb3e20
Removing intermediate container 4fd0ea665eaf
Step 2 : CMD curl -s http://ip.cn
---> Running in 6d14169fb841
---> af6a8441dcc9
Removing intermediate container 6d14169fb841
Successfully built af6a8441dcc9
[root@localhost mydocker]# docker run af6a8441dcc9
{"ip": "114.244.77.52", "country": "北京市", "city": "联通"}
DockerFile文件内容如下:
FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]
如果我们希望显示 HTTP 头信息,就需要加上 -i
参数,但是就会报错。
[root@localhost mydocker]# docker run c18008dfcc35 -i
Error response from daemon: Cannot start container 42d9aaf8ffabde5b000bea14673b4d2be86fa8c66c16d3feccece3dc4d2d2b59: [8] System error: exec: "-i": executable file not found in $PATH
我们可以看到可执行文件找不到的报错,executable file not found
。之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。因此这里的 -i
替换了原来的 CMD,而不是添加在原来的 curl -s http://ip.cn
后面。而 -i
根本不是命令,所以自然找不到。
那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:
$ docker run myip curl -s http://ip.cn -i
④ ENTRYPOINT测试步骤
复制并修改DockerFile文件为DockerFile3:
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
重复上面构建、运行步骤,结果如下:
① 在/mydocker/路径下创建路径mytomcat,并放入jdk与tomcat二进制压缩包
#纯粹为了copy命令使用
touch c.txt
② 在mytomcat目录下新建DockerFile文件
内容如下:
FROM centos
MAINTAINER jane<jane@qq.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u121-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.42.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_121
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.42
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.42
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-8.5.42/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-8.5.42/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-8.5.42/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.42/logs/catalina.out
③ 构建生成镜像
命令如下:
docker build -f DockerFile -t mytomcat8.5 .
详细过程如下所示:
[root@localhost mytomcat]# docker build -f DockerFile -t mytomcat8.5 .
Sending build context to Docker daemon 193 MB
Sending build context to Docker daemon
Step 0 : FROM centos
---> 495a24dc98e8
Step 1 : MAINTAINER jane<jane@qq.com>
---> Using cache
---> b2c306367103
Step 2 : COPY c.txt /usr/local/cincontainer.txt
---> 30125b712727
Removing intermediate container e7ce454acc1b
Step 3 : ADD jdk-8u121-linux-x64.tar.gz /usr/local/
---> a60edc35c1dd
Removing intermediate container a7d37532c8ed
Step 4 : ADD apache-tomcat-8.5.42.tar.gz /usr/local/
---> 835ce1e40fbb
Removing intermediate container 74877ed67a66
Step 5 : RUN yum -y install vim
---> Running in 632fbb5d8fab
CentOS-8 - AppStream 475 kB/s | 6.4 MB 00:13
CentOS-8 - Base 249 kB/s | 5.0 MB 00:20
CentOS-8 - Extras 2.0 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 297 kB/s | 39 kB 00:00
(2/5): vim-filesystem-8.0.1763-13.el8.noarch.rp 27 kB/s | 48 kB 00:01
(3/5): vim-enhanced-8.0.1763-13.el8.x86_64.rpm 667 kB/s | 1.4 MB 00:02
(4/5): which-2.21-10.el8.x86_64.rpm 170 kB/s | 49 kB 00:00
(5/5): vim-common-8.0.1763-13.el8.x86_64.rpm 524 kB/s | 6.3 MB 00:12
--------------------------------------------------------------------------------
Total 583 kB/s | 7.8 MB 00:13
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.3 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!
---> e810859c3774
Removing intermediate container 632fbb5d8fab
Step 6 : ENV MYPATH /usr/local
---> Running in 6f29ac3aab57
---> 3046102d4b97
Removing intermediate container 6f29ac3aab57
Step 7 : WORKDIR $MYPATH
---> Running in d72543dcc1e5
---> 26216526ef34
Removing intermediate container d72543dcc1e5
Step 8 : ENV JAVA_HOME /usr/local/jdk1.8.0_121
---> Running in 043966dc5dd5
---> 31e881b878b2
Removing intermediate container 043966dc5dd5
Step 9 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
---> Running in 426decc562b0
---> d211b87e14b6
Removing intermediate container 426decc562b0
Step 10 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.42
---> Running in e7bd1fb680d3
---> 5e9d3b1a9842
Removing intermediate container e7bd1fb680d3
Step 11 : ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.42
---> Running in 4751834bae65
---> 9a8f8a55f9db
Removing intermediate container 4751834bae65
Step 12 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
---> Running in abcd8a306cb4
---> e70a4215675b
Removing intermediate container abcd8a306cb4
Step 13 : EXPOSE 8080
---> Running in dd5ea962ca9e
---> f70b5c88c7b3
Removing intermediate container dd5ea962ca9e
Step 14 : CMD /usr/local/apache-tomcat-8.5.42/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.42/bin/logs/catalina.out
---> Running in 2e86e232814e
---> 5234d0ef08ec
Removing intermediate container 2e86e232814e
Successfully built 5234d0ef08ec
[root@localhost test]# docker exec 9169df7aa44f java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
[root@localhost test]#
④ 创建容器实例并运行
命令如下:
docker run -d -p 9080:8080 --name mytomcat8 -v /mydocker/mytomcat/test:/usr/local/apache-tomcat-8.5.42/webapps/test -v /mydocker/mytomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.42/logs --privileged=true mytomcat8.5
docker logs -f -t --tail 10 712e7776a36e
docker exec -it 9169df7aa44f /bin/bash
⑤ test里面放入项目文件
在test项目里面放入WEB-INF/web.xml 、a.jsp,将会同步到容器内webapps/test里面。
#9169df7aa44f 为容器ID
[root@9169df7aa44f test]# ls
WEB-INF a.jsp
[root@9169df7aa44f test]#
总结