Docker实战编写Dockerfile

Posted weifeng1463

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker实战编写Dockerfile相关的知识,希望对你有一定的参考价值。

一、创建Dockerfile文件

首先,需要创建一个目录来存放 Dockerfile 文件,目录名称可以任意,在目录里创建Dockerfile文件:

技术分享图片

二、Dockerfile 基本框架

Dockerfile一般包含下面几个部分:

  1. 基础镜像:以哪个镜像作为基础进行制作,用法是FROM 基础镜像名称
  2. 维护者信息:需要写下该Dockerfile编写人的姓名或邮箱,用法是MANITAINER 名字/邮箱
  3. 镜像操作命令:对基础镜像要进行的改造命令,比如安装新的软件,进行哪些特殊配置等,常见的是RUN 命令
  4. 容器启动命令:当基于该镜像的容器启动时需要执行哪些命令,常见的是CMD 命令ENTRYPOINT

在本节实验中,我们依次先把这四项信息填入文档。Dockerfile中的#标志后面为注释,可以不用写。

打开Dockerfile,依次输入下面的基本框架内容:

 

01
02
03
04
05
06
07
08
09
10
11
12
13
# Version 0.1
 
# 基础镜像
FROM debian:latest
 
# 维护者信息
 
# 镜像操作命令
RUN apt-get -yqq update && apt-get install -yqq apache2 && apt-get clean
 
# 容器启动命令
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

上面的Dockerfile非常简单,创建了一个apache的镜像。包含了最基本的四项信息。

其中FROM指定基础镜像,如果镜像名称中没有制定TAG,默认为latestRUN命令默认使用/bin/sh Shell执行,默认为root权限。如果命令过长需要换行,需要在行末尾加CMD命令也是默认在/bin/sh中执行,并且默认只能有一条,如果是多条CMD命令则只有最后一条执行。用户也可以在docker run命令创建容器时指定新的CMD命令来覆盖Dockerfile里的CMD

这个Dockerfile已经可以使用docker build创建新镜像了,先构建一个版本dockertest:0.1:

1
2
# 在dockertest目录,即Dockerfile所在的目录执行
docker build -t dockertest:0.1 .

构建需要安装apache2,会花几分钟,最后查看新创建的镜像:

技术分享图片

使用该镜像创建容器site1,将容器中的端口8888映射到本地80端口:

1
docker run -d -p 8888:80 --name site1 dockertest:0.1

使用浏览器打开localhost:8888进行测试,查看是否apache已运行:

技术分享图片

三、Dockerfile 编写常用命令

在上述基本的架构下,我们根据需求可以增加新的内容到Dockerfile中。后续的扩展操作都需要放置在Dockerfile的镜像操作部分。

1)指定容器运行的用户

该用户将作为后续的RUN命令执行的用户。命令使用方式,例如使用nginx用户来执行后续命令:

1
USER nginx

2)指定后续命令的执行目录

由于我们需要运行的是一个静态网站,将启动后的工作目录切换到/var/www/html目录:

1
WORKDIR /var/www/html

3)对外连接端口号

由于内部服务会启动Web服务,我们需要把对应的80端口暴露出来,可以提供给容器间互联使用,可以使用EXPOSE命令。

在镜像操作部分增加下面一句:

1
EXPOSE 80

4)设置容器主机名

ENV命令能够对容器内的环境变量进行设置,我们使用该命令设置由该镜像创建的容器的主机名为dockertest,向Dockerfile中增加下面一句:

1
ENV HOSTNAME dockertest

5)向镜像中增加文件

向镜像中添加文件有两种命令:COPY 和 ADD

COPY命令可以复制本地文件夹到镜像中:

1
COPY site1 /var/www/html

ADD 命令支持添加本地的tar压缩包到容器中指定目录,压缩包会被自动解压为目录,也可以自动下载URL并拷贝到镜像,例如:

1
2
ADD html.tar /var/www
ADD http://192.168.1.200/html.tar /var/www

6)CMD 与 ENTRYPOINT

ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与CMD的区别是不可以被docker run覆盖,会把docker run后面的参数当作传递给ENTRYPOINT指令的参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。docker run命令的-entrypoint参数可以把指定的参数继续传递给ENTRYPOINT

7)挂载数据卷

将apache访问的日志数据存储到宿主机可以访问的数据卷中:

1
VOLUME ["/var/log/apche2"]

8)设置容器内的环境变量

使用ENV设置一些apache启动的环境变量:

1
2
3
4
5
6
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apche2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apche2

9)使用 Supervisord

CMD如果只有一个命令,那如果我们需要运行多个服务怎么办呢?最好的办法是分别在不同的容器中运行,通过link进行连接。如果一定要在一个容器中运行多个服务可以考虑用Supervisord来进行进程管理,方式就是将多个启动命令放入到一个启动脚本中。

首先安装Supervisord,添加下面内容到Dockerfile:

1
2
RUN apt-get install -yqq supervisor
RUN mkdir -p /var/log/supervisor

拷贝配置文件到指定的目录:

1
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

其中supervisord.conf文件需要放在dockertest目录下,文件内容如下:

1
2
3
4
5
[supervisord]
nodaemon=true
 
[program:apache2]
command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2ctl -D FOREGROUND"

如果有多个服务需要启动可以在文件后继续添加[program:xxx],比如如果有ssh服务,可以增加[program:ssh]

修改CMD命令,启动Supervisord

1
CMD ["/usr/bin/supervisord"]

四、从 Dockerfile 创建镜像

在dockertest文件夹中有如下三个文件:

Dockerfile

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# debian apache2 php5 ssh vim
# Version 0.2
 
# 基础镜像
FROM debian:latest
 
# 维护者信息
 
# 设置debian的镜像,加快速度
RUN echo ‘deb http://mirrors.aliyun.com/debian/ jessie main non-free contrib‘ > /etc/apt/sources.list
&& echo ‘deb http://mirrors.aliyun.com/debian/ jessie-proposed-updates main non-free contrib‘ >> /etc/apt/sources.list
&& echo ‘deb http://mirrors.aliyun.com/debian-security/ jessie/updates main non-free contrib‘ >> /etc/apt/sources.list
 
# 镜像操作命令
RUN apt-get -yqq update
&& apt-get install -yqq supervisor openssh-server openssh-client vim
&& apt-get install -yqq apache2 php5 php5-mcrypt php5-mysql php5-imagick php5-json php5-curl
&& apt-get clean
 
# 设置 ssh,root密码为 www.wanglu.info
RUN echo ‘root:www.wanglu.info‘ | chpasswd
&& mkdir /var/run/sshd
&& sed -i ‘s/PermitRootLogin without-password/PermitRootLogin yes/‘ /etc/ssh/sshd_config
 
# 设置 supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
 
# 拷贝phpinfo.php文件到容器的 /var/www/html
COPY phpinfo.php /var/www/html
 
ENV HOSTNAME docker-test
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
 
EXPOSE 22 80
 
# 启动容器命令
CMD ["/usr/bin/supervisord"]

supervisord.conf

1
2
3
4
5
6
7
8
9
# supervisord configuration
[supervisord]
nodaemon=true
 
[program:ssh]
command=/usr/sbin/sshd -D
 
[program:apache]
command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2ctl -D FOREGROUND"

phpinfo.php

1
2
<?php
phpinfo();

在dockertest目录下使用 docker build 执行创建,-t参数指定镜像名称:

1
docker build -t dockertest:0.2 .

docker images 查看创建的新镜像已经出现在了镜像列表中:

技术分享图片

由该镜像创建新的容器site2,并映射本地的8080端口到容器的80端口、8022端口到容器的22端口:

1
docker run -d -p 8080:80 -p 8022:22 --name site2 dockertest:0.2

五、运行测试

部分操作截图:

技术分享图片

打开测试网页

技术分享图片

 

以上是关于Docker实战编写Dockerfile的主要内容,如果未能解决你的问题,请参考以下文章

实战docker,编写Dockerfile定制tomcat镜像,实现web应用在线部署

Docker容器dockerfile镜像实战案例

实战docker,编写Dockerfile定制tomcat8镜像,实现web应用在线部署

10.Docker技术入门与实战 --- 为镜像添加SSH服务

Docker基础学习笔记

Docker多阶段构建实战(multi-stage builds)