DockerFile
1. 概述
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。 可以参考官网文档: https://docs.docker.com/engine/reference/builder
2. 构建过程
- Dockerfile:需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
- Docker镜像:在用Dockerfile定义一个文件之后,
docker build
时会产生一个Docker镜像,当运行Docker镜像时会真正开始提供服务; - Docker容器:容器是直接提供服务的。
2.1 构建三步骤
- 编写Dockerfile文件
docker build
命令构建镜像docker run
依镜像运行容器实例
2.2 Dockerfile内容要点
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层并对镜像进行提交
2.3 Docker执行Dockerfile大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行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 | 用于指定在停止容器时发送给运行中的进程的信号。 |
这些命令作用域总结如下:
4. 通过Dockerfile自定义镜像
目标:制作Centos7镜像具备vim+ifconfig+jdk8特性
4.1 拉取基础镜像Centos7
- 拉取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
- commit当前的镜像
sh
[root@hadoop104 software]# docker commit -m="centos7 use aliyun repo" -a="jiebaba" 7de7b2f1b9ac jiebaba/mycentos:1.0
sha256:c9befb545f23e293ffe0db02c9890a798949ebe09bd899ff80a488173e84c5b2
4.2 下载jdk8
- 通过官网下载jdk8
- 上传到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