再没了解Dockerfile之前,假设我们docker需要运行一个centos容器,并且该容器需要安装部署redis、mysql、jdk等要求,我们之前的做法:
#拉取镜像
docker pull centos:7
#运行镜像
docker run -d centos:7
#进入容器
docker exec -it XXX镜像ID /bin/bash
#通过yum安装所需
yum install -y redis
#等等操作
以上是我们之前docker的操作方式,那么有没有一种可以直接一次性帮我们将这些命令都汇总起来,一次性执行呢? dcoker官方也考虑到了点,那就是使用我们的Dockerfile
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。Docker通过读取 Dockerfile可以快速构建我们所需的镜像。
官方的文档地址: https://docs.docker.com/engine/reference/builder/
#必须FROM开头指定镜像模版
FROM centos:7
#定义环境变量
ENV MYPATH /usr/local
#设置工作目录
WORKDIR $MYPATH
#指定作者
LABEL org.opencontainers.image.authors="micro"
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
CMD echo "success"
CMD /bin/bash
通过上面的命令,其实就是以centos为基础镜像,指定了工作目录(进入容器后默认进入该目录),并在原centos镜像基础上安装了vim、ifconfig命令,生成一个新的镜像
我大家可以复制上述Dockerfile指令来演示一下,首先按照博主之前设置的data目录,创建一个myfile文件夹用来存放我们本次的Dockerfile
#创建目录
mkdir /data/myfile
#进入目录
cd /data/myfile
#复制上述例子内容
vim Dockerfile
#构建镜像 注意语法后面有一个 .
docker build -t mycentos:1.0 .
注:最后的 . 代表本次执行的上下文路径,上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包
相信大家已经构建出了自己新的centos镜像,默认的centos镜像是不存在 vim 和 ifconfig 指令的,可以run起来测试一下指令是否生效。
基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是FORM
FROM centos:7
执行后面跟着的命令行命令,有两种格式:
第一种shell格式:(常用)
# <命令行命令> 等同于,在终端操作的 shell 命令。
RUN <命令行命令>
#如
RUN yum -y install vim
第二种exec格式:
RUN ["可执行文件", "参数1", "参数2"]
将宿主机中目录的文件拷贝到镜像,如果拷贝的是压缩文件会自动解压;
#将jdk 拷贝到镜像/usr/local/java/ 并解压
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
从上下文目录中复制文件或者目录到容器里指定路径,和ADD指令类似,区别就在于COPY指令不会帮我们解压;
用来在构建镜像过程中设置环境变量,如Dockerfile例子中,定义了MYPATH,后续的指令中可以通过 $MYPATH 引用
#定义环境变量
ENV MYPATH /usr/local
#设置工作目录
WORKDIR $MYPATH
容器数据匿名卷,用于数据保存和持久化工作,并不然,VOLUME指令只是起到了声明了容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。
注意不要认为和 -v 挂载数据卷作用一样,VOLUME指令并没有将匿名卷绑定到宿主机指定目录的功能,VOLUME只是指定了一个目录,用以在用户忘记启动时指定-v参数也可以保证容器的正常运行。
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
设定工作目录,用户登陆进入容器后默认的工作路径
CMD指令和RUN指令类似,但他们也有区别;
CMD 在docker run 时运行
RUN 在 docker build 时运行
如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
CMD 会被 docker run 之后的参数替换
CMD <shell 命令>
CMD ["<可执行文件或命令>","" ,"" ,...]
# 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
CMD ["" ,"" ,...]
ENTRYPOINT指令也是用来指定一个容器启动时要运行的命令,类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序
语法格式
ENTRYPOINT ["" ,"" ,"" ,...]
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD,这里的 CMD 等于是在给 ENTRYPOINT 传参
当指定了ENTRYPOINT后,CMD就不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令
如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参这里定义 newnginx.conf
假设已通过 Dockerfile 构建了 nginx:test 镜像:
命令 | 不传参运行 | 传参运行 |
---|---|---|
docker命令 | docker run nginx:test | docker run nginx:test -c /etc/nginx/new.conf |
生成容器内运行命令 | nginx -c /etc/nginx/nginx.conf | nginx -c /etc/nginx/new.conf |
经过上述演示,ENTRYPOINT 指令可以在执行 docker run 的时候可以指定运行所需的某些参数,从而无需一定传参运行
当前容器对外暴露出的端口,当 docker run -P 的时候容器会自动随机映射 EXPOSE 的端口
指定该镜像以什么样的用户去执行,如果都不指定默认是root
USER <用户名>[:<用户组>]
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
# 比如我们可以添加镜像的作者
LABEL org.opencontainers.image.authors="micro"
首先为了演示各指令用法,我们下载官网下载一个压缩包的jdk这里下载 jdk-8u171-linux-x64.tar.gz , 改造我们的Dockerfile例子
一切准备完成后 在Dockerfile相同目录下应该具备以下文件:
Dockerfile
jdk-8u171-linux-x64.tar.gz
FROM centos:7
#定义环境变量
ENV MYPATH /usr/local
#设置工作目录
WORKDIR $MYPATH
#指定作者
LABEL org.opencontainers.image.authors="micro"
#安装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-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
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
CMD echo "success"
CMD /bin/bash
完成Dockerfile文件编写,我们执行构建命令试试吧
docker build -t mycentos:1.1 .
本章节主要介绍了Dockerfile的用法以及Dockerfile的常用指令,大家可以根据自己的需求自由编写自己的Dockerfile文件进行测试,如果本章节内容对你有用,希望点赞收藏加关注,谢谢!
下一章:在Centos Stream 9上Docker的实操教程 - Docker Compose容器编排详解