DockerFile解析及案例

DockerFlie解析

        • Dockerfile是什么?
        • Dockerfile构建过程解析
        • Dockerfile体系结构(保留字指令)
        • 自定义centos镜像案例
        • CMD/ENTRYPOINT 镜像案例
        • tomcat镜像案例


Dockerfile是什么?

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建三步骤: 1. 编写dockerfile文件 2. docker build 3. docker run

在dockerhub网站上面以centos为例,查看其dockerfile的内容

FROM scratch
ADD centos-7-x86_64-docker.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="20200809" \
    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-08-09 00:00:00+01:00"

CMD ["/bin/bash"]

Base镜像(scratch):Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的


Dockerfile构建过程解析

Dockerfile基础知识

  • 1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • 2:指令按照从上到下,顺序执行
  • 3:#表示注释
  • 4:每条指令都会创建一个新的镜像层,并对镜像进行提交

Docker执行Dockerfile的大致流程

  • 1:docker从基础镜像运行一个容器
  • 2:执行一条指令并对容器作出修改
  • 3:执行类似docker commit的操作提交一个新的镜像层
  • 4:docker再基于刚提交的镜像运行一个新容器
  • 5:执行dockerfile中的下一条指令直到所有指令都执行完成

DockerFile 、Docker镜像、Docker容器的关系:

  1. Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

  2. Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;

  3. Docker容器,容器是直接提供服务的。
    DockerFile解析及案例_第1张图片


Dockerfile体系结构(保留字指令)

指令 作用
FROM 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令
EXPOSE 当前容器对外暴露出的端口
WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
ADD 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定一个容器启动时要运行的命令
ENTRYPOINT 指定一个容器启动时要运行的命令
ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

自定义centos镜像案例

背景:使用从dockerhub上面拉取的镜像是没有vim 和ifconfig 命令的,这里我们自定义一个镜像,使得我们的centos镜像创建容器时候就自带这两个命令

构建DockerFile文件

[root@bigdata01 mydocker]# cd /mydocker/
[root@bigdata01 mydocker]# vi dockerfile2 

FROM centos
MAINTAINER nice<[email protected]>
ENV mypath /usr/local
WORKDIR /tmp
RUN yum -y install vim 
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "success----ok"
CMD /bin/bash

Build Dockerfile

[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile2 -t nice/mycentos:1.3 .
Sending build context to Docker daemon  3.072kB
Step 1/10 : FROM centos
 ---> 831691599b88
Step 2/10 : MAINTAINER nice<[email protected]>
 ---> Running in 1bfae7ed3784
Removing intermediate container 1bfae7ed3784
 ---> 608ee480d3a5
Step 3/10 : ENV mypath /usr/local
 ---> Running in 5cde4bf46590
Removing intermediate container 5cde4bf46590
 ---> 3eaa07e83274
Step 4/10 : WORKDIR /tmp
 ---> Running in 924295eb2a3c
Removing intermediate container 924295eb2a3c
 ---> 33a0398d93d9
Step 5/10 : RUN yum -y install vim
 ---> Running in 623dedacee36
CentOS-8 - AppStream                            669 kB/s | 5.8 MB     00:08    
CentOS-8 - Base                                 329 kB/s | 2.2 MB     00:06    
CentOS-8 - Extras                               8.1 kB/s | 7.3 kB     00:00    
Dependencies resolved.

、、、、、、
Total download size: 323 k
Installed size: 1.0 M
Downloading Packages:
net-tools-2.0-0.51.20160912git.el8.x86_64.rpm   1.4 MB/s | 323 kB     00:00    
--------------------------------------------------------------------------------
Total                                           395 kB/s | 323 kB     00:00     
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 41b956ae87fe
 ---> 1a38831365ae
Step 7/10 : EXPOSE 80
 ---> Running in a8c44ccb84fa
Removing intermediate container a8c44ccb84fa
 ---> 74743b39aa23
Step 8/10 : CMD echo $MYPATH
 ---> Running in 320eb480e5c8
Removing intermediate container 320eb480e5c8
 ---> 6528ca7b7306
Step 9/10 : CMD echo "success----ok"
 ---> Running in 9f6bdf0a76c5
Removing intermediate container 9f6bdf0a76c5
 ---> 58635bf5cf92
Step 10/10 : CMD /bin/bash
 ---> Running in 8fbcefef7924
Removing intermediate container 8fbcefef7924
 ---> b9e08611155a
Successfully built b9e08611155a
Successfully tagged nice/mycentos:1.3

[root@bigdata01 mydocker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nice/mycentos       1.3                 b9e08611155a        30 seconds ago      295MB

run docker 容器

[root@bigdata01 mydocker]# docker run -it b9e08611155a
[root@d698b05d8ce9 tmp]# pwd
/tmp

以上可以知道,docker默认的工作目录是/tmp 目录,与我们设置的相同

使用docker history 命令查看镜像的构建历史

[root@bigdata01 mydocker]# docker history b9e08611155a
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
b9e08611155a        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
58635bf5cf92        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
6528ca7b7306        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
74743b39aa23        3 minutes ago       /bin/sh -c #(nop)  EXPOSE 80                    0B                  
1a38831365ae        3 minutes ago       /bin/sh -c yum -y install net-tools             22.7MB              
c02d91a59e73        3 minutes ago       /bin/sh -c yum -y install vim                   57.2MB              
33a0398d93d9        3 minutes ago       /bin/sh -c #(nop) WORKDIR /tmp                  0B                  
3eaa07e83274        3 minutes ago       /bin/sh -c #(nop)  ENV mypath=/usr/local        0B                  
608ee480d3a5        3 minutes ago       /bin/sh -c #(nop)  MAINTAINER nice
831691599b88        2 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           2 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:84700c11fcc969ac0…   215MB

CMD/ENTRYPOINT 镜像案例

CMD和ENTRYPOINT的区别?

  • 相同点:CMD和ENTRYPOINT都是指定一个容器启动时要运行的命令

  • 不同点:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换,而ENTRYPOINT在docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合

案例需求:构造两个镜像,一个基于CMD指令,另一个基于ENTRYPOINT指令,分别测试两个指令的区别与联系

编写两个dockerfile

# CMD
FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "http://ip.cn" ]

# ENTRYPOINT
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

构建镜像:

# 构建CMD镜像
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile-centos-cmd -t nice/centos-cmd:1.0
"docker build" requires exactly 1 argument.
See 'docker build --help'.

  age:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile-centos-cmd -t nice/centos-cmd:1.0 .
Sending build context to Docker daemon   5.12kB
Step 1/3 : FROM centos
 ---> 831691599b88
Step 2/3 : RUN yum install -y curl
 ---> Running in 9a15d717941c
CentOS-8 - AppStream                            1.5 MB/s | 5.8 MB     00:03    
CentOS-8 - Base                                 982 kB/s | 2.2 MB     00:02    
CentOS-8 - Extras                               4.1 kB/s | 7.3 kB     00:01    
Package curl-7.61.1-12.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
Removing intermediate container 9a15d717941c
 ---> 0e16c491ea85
Step 3/3 : CMD [ "curl", "-s", "http://ip.cn" ]
 ---> Running in 86fd8a2acbce
Removing intermediate container 86fd8a2acbce
 ---> ad79bf05cf4b
Successfully built ad79bf05cf4b
Successfully tagged nice/centos-cmd:1.0

# 构建ENTRYPOINT镜像
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile4 -t nice/centos-e:2.0 .
Sending build context to Docker daemon   5.12kB
Step 1/3 : FROM centos
 ---> 831691599b88
Step 2/3 : RUN yum install -y curl
 ---> Using cache
 ---> 0e16c491ea85
Step 3/3 : ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
 ---> Running in 7c33111bbca1
Removing intermediate container 7c33111bbca1
 ---> 553ff57039a7
Successfully built 553ff57039a7
Successfully tagged nice/centos-e:2.0
[root@bigdata01 mydocker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nice/centos-e       2.0                 553ff57039a7        17 seconds ago      235MB
nice/centos-cmd     1.0                 ad79bf05cf4b        11 minutes ago      235MB
nice/mycentos       1.3                 b9e08611155a        2 hours ago         295MB
nice/centos         latest              2da0623d0d63        2 weeks ago         215MB
nice/mytomcat       latest              f183c09f98b7        3 weeks ago         652MB
tomcat              latest              2ae23eb477aa        4 weeks ago         647MB
nginx               latest              08393e824c32        4 weeks ago         132MB
centos              latest              831691599b88        2 months ago        215MB
hello-world         latest              bf756fb1ae65        8 months ago        13.3kB

进行测试:

[root@bigdata01 mydocker]# docker run -it ad79bf05cf4b -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.

[root@bigdata01 mydocker]# docker run -it 553ff57039a7 -i
HTTP/1.1 301 Moved Permanently
Date: Thu, 03 Sep 2020 09:59:11 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Thu, 03 Sep 2020 10:59:11 GMT
Location: https://ip.cn/
cf-request-id: 04f500fa8f0000930aa20c8200000001
Server: cloudflare
CF-RAY: 5cce9dd74c8a930a-SJC
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

由以上可以看出使用CMD进行构建镜像的时候,在run容器的时候附加的命令会覆盖原来的CMD的命令,但是在使用ENTRYPOINT构建的进行,在run的时候附加的命令会追加到原来命令的后面组合成一个新的命令


tomcat镜像案例

目标:从centos构建一个tomcat镜像,安装JDK和tomcat ,配置共享目录,并使用案例进行测试

  • 1.创建文件夹用于存放我们的文件
  • 2.上传tomcat 和JDK的压缩包
  • 3.编写DockerFile 文件
  • 4.创建c.txt 用于测试文件移动
  • 5.创建test 和tomcat-logs文件夹
mkdir -p /mydocker/mytomcat
[root@bigdata01 mytomcat]# tree
.
├── apache-tomcat-8.5.34.tar.gz
├── c.txt
├── Dockerfile
├── jdk-8u221-linux-x64.tar.gz
└── test
│   ├── hello.jsp
│   └── WEB-INF
│       └── web.xml
└── tomcat-logs

Dockerfile 的内容如下:

FROM centos
MAINTAINER    nice<[email protected]>

#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt

#把java与tomcat添加到容器中
ADD jdk-8u221-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.34.tar.gz /usr/local/

#安装vim编辑器
RUN yum -y install vim

#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/localWORKDIR $MYPATH

#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_221
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.34
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.34
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

#容器运行时监听的端口
EXPOSE 8080

#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-8.5.34/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-8.5.34/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-8.5.34/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.34/bin/logs/catalina.out

构建镜像

docker build -f /mydocker/mytomcat/Dockerfile -t nice/tomcat:1.0 .

启动容器

docker run -d -p 8888:8080 --name tomcat2 \
-v /mydocker/mytomcat/test:/usr/local/apache-tomcat-8.5.34/webapps/test \
-v /mydocker/mytomcat/tomcat-logs/:/usr/local/apache-tomcat-8.5.34/logs \
--privileged=true \
f29ace801e39

浏览器访问地址:http://192.168.52.50:8888/ 出现tomcat的猫图像
DockerFile解析及案例_第2张图片
在test文件夹下面创建WEB-INF文件夹和hello.jsp,并且在WEB-INF里面创建web.xml 文件
hello.jsp 的内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    -----------welcome------------
    <%="i am in docker tomcat self "%>
    <br>
    <br>
    <% System.out.println("=============docker tomcat self");%>
  </body>
</html>

web.xml 的内容如下:


<web-app xmlns="http://www.example.org/web-app_2_5"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
         version="2.5">

          <display-name>testdisplay-name>
web-app>

创建之后重启容器,因为在本机的目录创建的文件,这里是和容器内的目录共享,所以重启容器之后即可访问测试

docker restart  containerID

浏览器访问:http://192.168.52.50:8888/test/hello.jsp 访问成功
DockerFile解析及案例_第3张图片

你可能感兴趣的:(Docker学习指南)