轻松创建 docker image

在 Docker 技术出现之前, 搭建 lab 环境复现问题实在是件非常让人头疼的事情. 按照传统的方式搭建 LAB 环境非常麻烦. 比如你需要测试 nginx 或是 ftp, 我们需要安装 linux 服务器, 配置网络, 分配 IP, 更新软件源, 安装软件包, 调整配置文件… 而 Docker 的出现彻底解放了这些繁琐的工作! 通过一个 Dockerfile, 用户可以build 出符合自己需要的 docker image 并在几分钟内拉起一个服务.

Dockerfile

要创建自己的 docker image, 最重要的就是这个 Dockerfile 啦! Dockerfile 是一个纯文本文件, 里面包含了创建 docker image 的各种”指令”. 简单来说docker 会一步步执行 Dockerfile 中的命令来完成一个image 的构建. 比如我们来看一个简单的 Dockerfile:

1
2
3
4
5
6
7
FROM ubuntu:18.04
RUN apt-get -yqq update && apt-get -yqq install nginx
RUN mkdir -p /var/www/html/website
ADD nginx/global.conf /etc/nginx/conf.d/
ADD nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD /bin/sh -c nginx

其实不用过多解释大家应该基本也能理解这些语句的含义:

  • FROM ubuntu:18.04: 以官方的ubuntu 18.04 为模板
  • RUN apt-get -yqq update && apt-get -yqq install nginx: 执行 apt 更新并且安装 nginx 软件包
  • RUN mkdir -p /var/www/html/website: 在 docker image 中创建存放站点的目录
  • ADD nginx/global.conf /etc/nginx/conf.d/: 当前 Dockerfile 同级目录中的 nginx/global.conf 放入 container 中的 /etc/nginx/conf.d/
  • ADD nginx/nginx.conf /etc/nginx/nginx.conf: 当前目录中子目录nginx/nginx.conf 覆盖 container 中的/etc/nginx/nginx.conf
  • EXPOSE 80: container 开启 80 端口接收外部的访问

在 nginx/nginx.conf 中是和 nginx server 本身相关的配置参数. 在其中比较重要的是 daemon off; 这个参数使得nginx 保持在container 的前端运行, 从而确保服务不被终止.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cat nginx.conf
user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;

events { }

http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
}

在 nginx/global.conf 中, 是我们网站的配置. 可以看到我们将网站的 root 指定为在 Dockerfile 中创建的目录 /var/www/html/website, 并且也指定了对应的日志目录.

1
2
3
4
5
6
7
8
9
10
server {
listen 0.0.0.0:80;
server_name _;

root /var/www/html/website;
index index.html index.htm;

access_log /var/log/nginx/default_access.log;
error_log /var/log/nginx/default_error.log;
}

Build

完成了上面的准备工作后, 我们就可以开始 build 阶段的工作啦! 这一步只需要一条命令即可, 不过一定记得执行的时候一定切换到 Dockerfile 文件所在的目录中哦! 另外命令的最后有一个点表示 Dockerfile的路径, 千万别漏啦.(当然你也可以写 Dockerfile 的绝对路径. )

1
docker build -t "m4n/nginx_demo" .

随后docker 就会依据你的 Dockerfile 中的指令一步一步完成 image 的打包操作. 很快你的 image 就制作完毕了.

启动

image 制作完毕后, 我们可以试试看用它拉起一个镜像:

1
$ docker run -d -p 80 --name first_site -v $PWD/website:/var/www/html/website m4n/nginx_demo nginx

我们来了解下这条命令中的几个参数:

  • -d 后台运行容器
  • -p: 端口映射. 比如 -p 3333:80 指定主机的3333端口映射到容器的80端口; 直接写也表示直接将宿主机的 80 端口映射到容器的端口 80
  • -v 本地目录:容器目录. 将宿主机本地目录中的 website 链接到容器中的 /var/www/html/website 这个目录中. ( /var/www/html/website 就是上面 docker image 中的 nginx 存放站点文件的目录) 这种挂载卷的方式打通了宿主机与容器间的文件共享. 这样我们就可以在编辑本地website文件夹中的index.html内容的同时, 使得container 里的nginx 也能感知到这个变化.

当然爱动脑筋的同学肯定想到了, 如果要对 nginx.conf 或者 global.conf 进行编辑, 只需要将它们与容器中的文件通过参数 -v 进行映射即可.

1
docker run --name nginx -p 80:80 -v nginx/nginx.conf:/etc/nginx/nginx.conf -v /var/log:/var/log/nginx -v nginx/global.conf:/etc/nginx/conf.d/global.conf -d nginx

Dockerfile 的编写还有许多用法, 具体可以参考Dockerfile reference