Skip to content

DockerFile

1. 概述

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
Alt text 可以参考官网文档: https://docs.docker.com/engine/reference/builder

2. 构建过程

Alt text

  • Dockerfile:需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
  • Docker镜像:在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行Docker镜像时会真正开始提供服务;
  • Docker容器:容器是直接提供服务的。

2.1 构建三步骤

  1. 编写Dockerfile文件
  2. docker build命令构建镜像
  3. docker run依镜像运行容器实例

2.2 Dockerfile内容要点

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

2.3 Docker执行Dockerfile大致流程

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

2.4 Dockerfile和Docker镜像容器的关系

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
    Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

3. DockerFile常用保留字指令

保留字描述
FROM基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from
MAINTAINER镜像维护者的姓名和邮箱地址, 已经过时,被LABEL取代
LABEL为镜像添加元数据,包括描述、版本和维护者等。
ENV用来在构建镜像过程中设置环境变量, 下面后续的指令中可以直接使用
ARG定义构建时变量,可在 Dockerfile 中使用但不会在容器中保留。
USER指定该镜像以什么样的用户去执行,如果都不指定,默认是root
EXPOSE当前容器对外暴露出的端口
ADD将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
COPY类似ADD,拷贝文件和目录到镜像中。
格式为COPY src dest或者COPY ["src", "dest"],和ADD的区别是不支持解压
VOLUME容器数据卷,用于数据保存和持久化工作
CMD指定容器启动后的要干的事情,Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,另外CMD会被 docker run之后的参数替换, 也就是说如果docker run后面加了参数,会把Dockerfile中最后一个CMD覆盖。
和RUN命令的区别:RUN是在docker build时运行,CMD是在docker run时运行。
ENTRYPOINT用来指定容器启动时要运行的命令,类似于CMD指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序。
也就是说ENTRYPOINT可以和CMD一起用,一般是变参>才会使用CMD ,这里的CMD等于是在给 ENTRYPOINT 传参。当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,这两个命令一起使用可以理解变成单独一个新命令, 优点:在执行docker run的时候可以指定ENTRYPOINT运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
RUN容器构建时需要运行的命令,在docker build时运行。shell格式(命令行命令);exec格式(["可执行文件","参数1","参数2", ...])
WORKDIR指定在创建容器后,终端默认登陆的进来工作目录
HEALTHCHECK用于指定一个命令来检查容器的健康状态。比如HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000/
ONBUILD用于定义当基础镜像被用作其他 Dockerfile 的父镜像时应该执行的指令。
STOPSIGNAL用于指定在停止容器时发送给运行中的进程的信号。

这些命令作用域总结如下:
Alt text

4. 通过Dockerfile自定义镜像

目标:制作Centos7镜像具备vim+ifconfig+jdk8特性

4.1 拉取基础镜像Centos7

  1. 拉取centos7镜像
sh
[root@hadoop104 redis]# docker pull centos:7
7: Pulling from library/centos
2d473b07cdd5: Pull complete 
Digest: sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
Status: Downloaded newer image for centos:7
docker.io/library/centos:7
[root@hadoop104 redis]# docker images | grep "centos"
centos                                                          7             eeb6ee3f44bd   3 years ago     204MB

2.由于后续步骤要通过yum安装vim, 为了顺利安装需要将原始centos镜像设置Yum源

sh
## 先运行镜像centos7, 挂载数据卷
[root@hadoop104 software]# docker run -it -v /tmp/repo/:/tmp/repo --name="centos7" centos:7 /bin/bash
## 另外启动一个终端,在宿主机上下载阿里的镜像源repo文件
[root@hadoop104 repo]# wget https://mirrors.aliyun.com/repo/Centos-7.repo
## 回到centos7的docker容器中终端
[root@7de7b2f1b9ac repo]# ll
total 4
-rw-r--r--. 1 root root 2523 Aug  4  2022 Centos-7.repo
## 备份以前的repo
[root@7de7b2f1b9ac repo]# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
## 使用阿里的repo
[root@7de7b2f1b9ac repo]# mv Centos-7.repo /etc/yum.repos.d/CentOS-Base.repo
## 清理旧缓存数据,缓存新数据
[root@7de7b2f1b9ac repo]# yum clean all
[root@7de7b2f1b9ac repo]# yum makecache
  1. commit当前的镜像
sh
[root@hadoop104 software]# docker commit -m="centos7 use aliyun repo" -a="jiebaba" 7de7b2f1b9ac jiebaba/mycentos:1.0
sha256:c9befb545f23e293ffe0db02c9890a798949ebe09bd899ff80a488173e84c5b2

4.2 下载jdk8

  1. 通过官网下载jdk8
  2. 上传到Docker服务器上
sh
[root@hadoop104 software]# ll
总用量 601716
-rw-rw-r--. 1 jack jack 141887242 8月   3 21:04 jdk-8u391-linux-x64.tar.gz

4.3 编写Dockerfile文件

docker
FROM jiebaba/mycentos:1.0
LABEL version="1.0" maintainer="jiebaba@example.com"  
 
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u391-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u391-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_391
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
 
EXPOSE 80
 
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash

4.4 构建build

格式:docker build -t 新镜像名字:TAG . 需要注意的是TAG后面有个空格,有个点

sh
[root@hadoop104 software]# ll
总用量 601720
-rw-r--r--. 1 root root       761 10月 23 21:34 Dockerfile
-rw-rw-r--. 1 jack jack 141887242 8月   3 21:04 jdk-8u391-linux-x64.tar.gz
[root@hadoop104 software]# docker build -t mycentosjava8 .
[+] Building 314.3s (12/12) FINISHED                                                                                                  docker:default
 => [internal] load build definition from Dockerfile                                                                                            0.0s
 => => transferring dockerfile: 865B                                                                                                            0.0s
 => [internal] load metadata for docker.io/jiebaba/mycentos:1.0                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                               0.0s
 => => transferring context: 2B                                                                                                                 0.0s
 => [1/7] FROM docker.io/jiebaba/mycentos:1.0                                                                                                   0.0s
 => [internal] load build context                                                                                                               0.0s
 => => transferring context: 103B                                                                                                               0.0s
 => CACHED [2/7] WORKDIR /usr/local                                                                                                             0.0s
 => [3/7] RUN yum -y install vim                                                                                                              197.8s
 => [4/7] RUN yum -y install net-tools                                                                                                         12.4s 
 => [5/7] RUN yum -y install glibc.i686                                                                                                        93.3s 
 => [6/7] RUN mkdir /usr/local/java                                                                                                             0.4s 
 => [7/7] ADD jdk-8u391-linux-x64.tar.gz /usr/local/java/                                                                                       5.1s 
 => exporting to image                                                                                                                          5.3s 
 => => exporting layers                                                                                                                         5.2s 
 => => writing image sha256:8aa2d1113fb15d291e6e6adb10768428ab93556bf2c35662f4e5db2db5642d19                                                    0.0s 
 => => naming to docker.io/library/mycentosjava8
 [root@hadoop104 software]# docker images
REPOSITORY                                                      TAG           IMAGE ID       CREATED          SIZE
mycentosjava8                                                   latest        8aa2d1113fb1   41 minutes ago   1.88GB
jiebaba/mycentos                                                1.0           c9befb545f23   56 minutes ago   736MB

4.5 运行新镜像

sh
[root@hadoop104 software]# docker run -it mycentosjava8 /bin/bash
[root@2bb58fd3e17f local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.5  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:05  txqueuelen 0  (Ethernet)
        RX packets 7  bytes 586 (586.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@2bb58fd3e17f local]# pwd      
/usr/local

5. 虚悬镜像

仓库名、标签都是<none>的镜像,俗称dangling image。比如执行构建命令docker build .,但没有指定容器信息
查看虚悬镜像:

sh
[root@hadoop104 software]# docker image ls -f dangling=true

虚悬镜像已经失去存在价值,可以删除:

sh
[root@hadoop104 software]# docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B