关于docker那点事儿——Dockerfile编写
Posted 偷学技术的梁胖胖yo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于docker那点事儿——Dockerfile编写相关的知识,希望对你有一定的参考价值。
Dockerfile编写
前言
Dockerfile 说白了就是构建镜像的一个文件。它里面描述了一条条的指令,每一条指令都会构建新的一层。当执行
docker build
时,docker会按照我们Dockefile里预编写好的指令,去一层层构建,从而构建出一个新的镜像。
一、Dockerfile创建镜像
- 创建目录
mkdir any_name
cd any_name
- 编写Dockerfile文件
vim Dockerfile
# This is a comment
FROM daocloud.io/library/nginx
MAINTAINER liang liang@localhost.localdomain
RUN mkdir /test
*注: 如果文件中有执行失败的指令,那么创建出来的镜像名字和tag都为none
- 构建镜像
docker build -t liang/nginx:v1 . # . 一定要有 表示Dockerfile在当前目录 如果文件名不是Dockerfile 使用 -f 指定文件
二、Dockerfile常用指令
1、FROM 拉取基础镜像
功能为指定基础镜像,并且必须是第一条指令。如果不以任何镜像为基础,那么写法为:FROM scratch。
语法:FROM <image>:<tag> 其中<tag>为可选项,默认为latest
2、RUN 构建容器时执行命令
RUN命令有两种格式
Ⅰ. RUN <command> # shell方式
Ⅱ. RUN ["executable", "param1", "param2"] # 类似于函数调用,可将executable理解成为可执行文件,后面就是两个参数
*注:多行命令不要写多个RUN,写在一个RUN里,原因是Dockerfile中每一个指令都会建立一层
3、MAINTAINER
MAINTAINER <name> # 指定作者
4、CMD 容器启动时要运行的命令
语法:Ⅰ. CMD ["executable","param1","param2"] # CMD [ "sh", "-c", "echo $HOME" ]
Ⅱ. CMD ["param1","param2"] # CMD [ "echo", "$HOME" ]
Ⅲ. CMD command param1 param2 # shell形式
*注:Ⅰ和Ⅱ两种方式一定要用双引号,千万不能写成单引号
5、ENV 设置环境变量
语法:ENV <key>=<value> ... # 可一次设置多个
6、ADD 复制命令 类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用
语法:Ⅰ. ADD <src>... <dest>
Ⅱ. ADD ["<src>",... "<dest>"]
<dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
<src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
7、COPY 复制命令
语法:Ⅰ. COPY <src>... <dest>
Ⅱ. COPY ["<src>",... "<dest>"]
8、EXPOSE 暴露监听端口给外部
*注:EXPOSE并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上-p参数
9、WORKDIR 设置工作目录
语法:WORKDIR /path/to/workdir
对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。
10、VOLUME 实现挂载功能,可以将本地文件夹或者其他容器中的文件夹挂在到这个容器
语法:VOLUME ["/data"]
*注:一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷
三、示例
1、Dockerfile构建nginx镜像
FROM centos:7.2.1511
ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
RUN yum -y install epel* gcc openssl openssl-devel pcre-devel zlib-devel
ADD nginx-1.14.0.tar.gz /opt/
WORKDIR /opt/nginx-1.14.0
RUN ./configure --prefix=/opt/nginx --http-log-path=/opt/nginx/logs/access.log --error-log-path=/opt/nginx/logs/error.log --http-client-body-temp-path=/opt/nginx/client/ --http-proxy-temp-path=/opt/nginx/proxy/ --with-http_stub_status_module --with-file-aio --with-http_flv_module --with-http_gzip_static_module --with-stream --with-threads --user=www --group=www
RUN make && make install
RUN groupadd www && useradd -g www www
WORKDIR /opt/nginx
RUN rm -rf /opt/nginx-1.14.0
ENV NGINX_HOME=/opt/nginx
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/nginx/sbin
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
*注:此只是个例子,实际中如果没有满足需求的base image,如java程序使用java:8作为base image,可以使用Alpine镜像作为base image,轻量级且命令丰富,比centos镜像更适合做base image
2、Dockerfile构建微服务
#cat Dockerfile
FROM java:8
MAINTAINER liang_20210511
#ENV TZ=Asia/Shanghai
#ENV LANG=en_US.UTF-8
#ENV LANGUAGE=en_US:en
#ENV LC_ALL=en_US.UTF-8
ENV JAVA_OPTS="-Xms512m -Xmx512m"
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD cmdb-server.tar /
WORKDIR /cmdb-server
EXPOSE 10013
#CMD ["java","-jar","cmdb-server.jar","-Dfile.encoding=utf-8"]
ENTRYPOINT ["/cmdb-server/entrypoint.sh"]
#cat entrypoint.sh
#!/bin/sh
nohup java -server $JAVA_OPTS -jar cmdb-server.jar >/dev/null 2>&1 &
sleep 1
if [ $? -eq 0 ];then
tail -f logs/cmdb-server.log
fi
四、CMD与ENTRYPOINT比较
cmd 和 entrypoint 指令都是用来指定容器启动时运行的命令。并且都有exec与shell两种模式。推荐使用exec模式,这样可以使容器接收的KILL信号,从而优雅的退出。这里牵扯到容器的daemon进程来管理容器的生命周期,以后有机会我们以后专门拿出来去探讨。
cmd 指令
cmd 指令的目的是:为容器提供默认的执行命令。
cmd 指令有三种使用方式,其中的一种是为 entrypoint 提供默认的参数:
cmd ["param1","param2"]
另外两种使用方式分别是 exec 模式和 shell 模式:
cmd ["executable","param1","param2"]
cmd command param1 param2
注意命令行参数可以覆盖 cmd 指令的设置,但是只能是重写,却不能给 cmd 中的命令通过命令行传递参数。我们可以通过docker run
参数的方式覆盖 cmd 指令提供的默认命令。
entrypoint 指令
entrypoint 指令的目的也是为容器指定默认执行的任务。
entrypoint 指令有两种使用方式, exec 模式和 shell 模式:
entrypoint ["executable", "param1", "param2"]
entrypoint command param1 param2
在这里entrypoint 有一个特殊的用法,传参。
1、当我们使用exec模式时,docker run的指令可以作为参数传递给entrypoint 命令。比如:
from centos
entrypoint [ "top", "-n" ]
当我们执行docker run -- rm centos:test 1
此时容器里执行的命令:top -n 1
2、cmd指令给entrypoint 传参,比如:
from centos
entrypoint [ "top", "-n" ]
cmd [ "1" ]
当我们执行docker run -- rm centos:test
此时容器里执行的命令:top -n -1
3、docker run的指令覆盖cmd指令,传参给entrypoint
from centos
entrypoint [ "top", "-n" ]
cmd [ "1" ]
当我们执行docker run -- rm centos:test 3
此时容器里执行的命令:top -n -3
其实cmd指令与entrypoint指令远比这些要复杂:
当然,大家想深入了解的也可以参考官方给的解释自行实践对比一下:官方链接
以上是关于关于docker那点事儿——Dockerfile编写的主要内容,如果未能解决你的问题,请参考以下文章