一、什么是 Dockerfile?

Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了Dockerfile之后,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成镜像即可,省去了敲命令的麻烦。

二、Dockerfile文件格式

Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令。

一开始必须要指明所基于的基础镜像名称,接下来一般会说明维护者信息,后面则是镜像操作指令,例如 RUN 指令。每执行一条RUN 指令,镜像添加新的一层,并提交;最后是 CMD 指令,来指明运行容器时的操作命令。

# 1、第一行必须指定 基础镜像信息
# 定制的镜像都是基于 FROM 的镜像,这里的ubuntu 就是定制需要的基础镜像。
# 后续的操作都是基于 nginx。
# FROM <image>:<tag>
FROM ubuntu

# 2、维护者信息
MAINTAINER docker_user docker_user@email.com

# 3、镜像操作指令
# RUN:用于执行后面跟着的命令行命令。 有以下俩种格式:
# shell 格式:RUN <命令行命令>
# exec 格式:RUN ["可执行文件", "参数1", "参数2"]
# 例如:RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# 4、容器启动执行指令
CMD /usr/sbin/nginx

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。

例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

三、构建 Docker 镜像

docker build 命令会根据 Dockerfile 文件及上下文构建新 Docker 镜像。构建上下文是指 Dockerfile 所在的本地路径或一个URL(Git仓库地址)。构建上下文环境会被递归处理,所以构建所指定的路径还包括了子目录,而URL还包括了其中指定的子模块。

# 构建镜像,将当前目录做为构建上下文
docker build .

# Dockerfile 一般位于构建上下文的根目录下, 也可以通过-f指定该文件的位置
# 还可以通过-t参数指定构建成镜像的仓库、标签
docker build -f /path/to/Dockerfile -t nginx:v1 .

什么是上下文路径?

上下文路径是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

四、制作一个简单的Dockerfile

1、准备一个nginx的基础镜像。

docker pull library/ngnix

在镜像列表中会看到我们从远程仓库中获取的nginx镜像。

docker images | grep ngnix

2、准备好了基础镜像,编写Dockerfile

以定制 nginx 镜像为例,在一个空白目录中,建立一个文本文件,并命名为 Dockerfile

mkdir mydocker
cd mydocker
touch Dockerfile

构建一个 Dockerfile 内容如下:

FROM nginx
RUN echo '<h1>hello, docker!</h1>' > /usr/share/nginx/html/index.html

这个 Dockerfile 一共就两行涉及到了两条指令:FROM 和 RUN,FROM 表示获取指定基础镜像,RUN 执行命令,在执行的过程中重写了 nginx 的默认页面信息,将信息替换为:Hello, Docker!。

4、用Dockerfile 来构建镜像

在 Dockerfile 文件所在目录执行:

docker build -t nginx:v1 .

构建完成之后,使用 docker images 命令查看所有镜像,如果存在 REPOSITORY 为 nginx 和 TAG 是 v1 的信息,就表示构建成功。

docker images | grep nginx:v1
docker images nginx:v1

5、接下来使用 docker run 命令来启动容器

docker run  --name docker_nginx_v1  -itd -p 80:80 nginx:v1

这条命令会用 nginx 镜像启动一个容器,命名为docker_nginx_v1,并且映射了 80 端口,这样我们可以用浏览器去访问这个 nginx 服务器

6、访问这个 nginx 服务器

curl 127.0.0.1

返回如下信息: ​​<h1>hello, docker!</h1>​​ ,则表示成功。

7、查看运行的容器docker_nginx_v1

docker ps | grep docker_nginx_v1

8、查看容器日志

# docker logs -f -t 容器ID
docker logs -f -t 0ad2db0945d7e717f5d02ad3d1a8b548ed50ba8570179638ff4b3df2fb127c7f

9、进入容器内

docker exec -i -t  docker_nginx_v1 /bin/bash

10、根据容器ID删除容器

docker rm -f e3811b67f691

11、根据镜像ID删除镜像

# docker rmi [Image ID]
docker rmi 43757978f723

至此,一个简单的Docker镜像就制作完成,并且能够通过镜像启动容器运行了。