Docker实战(五)编写Dockerfile

日期:2016年05月03日 作者: 分类:运维 浏览:6329

目标:编写Dockerfile搭建LAMP环境,并能通过ssh连接到容器。

一、创建Dockerfile文件

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

编写Dockerfile

二、Dockerfile 基本框架

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

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

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

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

# Version 0.1

# 基础镜像
FROM debian:latest

# 维护者信息
MAINTAINER wl1524520@gmail.com

# 镜像操作命令
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:

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

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

编写Dockerfile

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

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

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

编写Dockerfile

三、Dockerfile 编写常用命令

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

1)指定容器运行的用户

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

USER nginx

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

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

WORKDIR /var/www/html

3)对外连接端口号

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

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

EXPOSE 80

4)设置容器主机名

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

ENV HOSTNAME dockertest

5)向镜像中增加文件

向镜像中添加文件有两种命令:COPYADD

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

COPY site1 /var/www/html

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

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访问的日志数据存储到宿主机可以访问的数据卷中:

VOLUME ["/var/log/apche2"]

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

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

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:

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

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

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

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

[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

CMD ["/usr/bin/supervisord"]

四、从 Dockerfile 创建镜像

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

Dockerfile

# debian apache2 php5 ssh vim
# Version 0.2

# 基础镜像
FROM debian:latest

# 维护者信息
MAINTAINER wl1524520@gmail.com

# 设置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

# 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

<?php
phpinfo();

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

docker build -t dockertest:0.2 . 

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

编写Dockerfile

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

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

五、运行测试

部分操作截图:

编写Dockerfile

打开测试网页

编写Dockerfile

 

PS:本Docker实战教程系列中使用的操作系统是基于Debian的LMDE2,教程中的命令均已运行测试,如有雷同,我抄你的!!!

标签:

除非注明,戊辰人博客文章均为原创,转载请以链接形式标明本文地址

本文地址:https://wanglu.info/2016/05/1180.html