Dockerfile文件

Dockerfile常用指令

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

Dockerfile 的指令是从上到下依次执行。其实跟我们直接敲命令差不多。

1
2
3
4
5
6
7
# 一些常见指令
FROM:指定基础镜像,必须
WORKDIR :设置指令的工作目录
COPY :将文件或目录复制到镜像中,第一个参数是宿主机文件,第二个是容器
RUN :镜像创建阶段中执行的命令
CMD :容器创建阶段中执行的命令,可以被覆盖。例如在docker run 镜像id xxxx时
EXPOSE :声明端口号

RUN 和 CMD 的区别:RUN 是在创建镜像时执行的命令,一般是安装、下载、创建文件之类的。CMD 是在创建容器时才会执行的命令,一般是启动程序的命令。

CMD 两种写法

exec 模式:不会通过 shell 执行相关的命令,所以向 $HOME 这样的环境变量是获取不到的。

格式:CMD ["可执行文件","参数1","参数2"]

shell 模式:docker 以 /bin/sh -c command 的方式执行命令,也就是说容器的 1 号进程是 bash 进程。

格式:CMD command

例如:

CMD ["/bin/echo","hello"],会输出 hello。

CMD echo hello,也会输出 hello,但是他其实是这样的 CMD ["","-c","echo hello"]

CMD echo $HOME 实际执行是 CMD [ "sh", "-c", "echo $HOME" ]

推荐使用 exec 模式,如果命令太多可以写成一个脚本,然后运行这个脚本。

Dockerfile例子

一个简单的 Dockerfile:安装 Nginx 并启动

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 需要一个Debian 9.4的镜像
FROM debian:9.4  

# 上传apt源配置
COPY ./sources.list /etc/apt/sources.list
# 安装Nginx
RUN apt update ; apt install nginx -y
# 声明端口,仅仅只是一个声明,描述需要哪些端口
EXPOSE 80

#启动Nginx和php
COPY start_nginx_php.sh /root/start_nginx_php.sh
WORKDIR /root/
RUN chmod 777 /root/start_nginx_php.sh
CMD ["sh","-c","./start_nginx_php.sh"]

FROM debian:9.4:指定一个基础镜像,需要一个 Debian 9.4 的镜像

COPY ./sources.list /etc/apt/sources.list:将宿主机的 ./sources.list 复制到容器的 /etc/apt/sources.list,这个 sources.list 文件,是提前准备好的apt 源。

RUN apt update ; apt install nginx -y:执行两条命令,更新源和安装 Nginx,这里用了分隔符执行两个命令,也可以分开写,用两个 RUN。

COPY start_nginx_php.sh /root/start_nginx_php.sh:将Nginx启动脚本复制到容器。脚本内容在后面说。

WORKDIR /root/:来到容器的 /root/ 目录下,也就是存放 Nginx 启动脚本的目录。

RUN chmod 777 /root/start_nginx_php.sh:赋予 Nginx 启动脚本执行权限。

CMD ["sh","-c","./start_nginx_php.sh"]:运行脚本。

先看看启动脚本内容

1
2
3
#!/bin/sh
/usr/sbin/service nginx start
/bin/bash

docker 的机制

1、Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。

2、docker 容器运行必须有一个前台进程,如果没有前台进程执行,容器认为空闲,就会自行退出。一般常见的启动参数是 docker run -dit centos /bin/bash/bin/bash 就是一个前台进程,你也可以用 top 之类的命令。

3、使用 CMD service nginx start 命令作为容器启动命令的话,这个命令执行成功后就会退出,紧接着容器也会自动退出。对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

4、使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "service nginx start"],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。

5、所以在启动脚本当中最后是 /bin/bash 命令。防止容器退出。也可以将 nginx 放到前台运行 CMD ["nginx", "-g", "daemon off;"]

注意:docker run xxxxxxxxxxxxx /bin/bash ,这里的/bin/bash 会覆盖掉 CMD 的命令。

0%