文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

短小精悍的Dockerfile能够构建出Docker 镜像和容器,而本质上,他就是Docker engine运行一系列的命令后得到的镜像,然后把这个镜像运行起来这样就得到了容器。

让我们在构建自己的镜像之前线看个例子。

这是RethinkDB的Dockerfile,一个开源,实时的数据库。

dockerfile FROM debian:jessie

MAINTAINER Daniel Alan Miller dalanmiller@rethinkdb.com

RUN apt-key adv --keyserver pgp.mit.edu --recv-keys 1614552E5765227AEC39EFCFA7E00EF33A8F2399 RUN echo "deb http://download.rethinkdb.com/apt jessie main" > /etc/apt/sources.list.d/rethinkdb.list

ENV RETHINKDBPACKAGEVERSION 2.0.4~0jessie

RUN apt-get update \ && apt-get install -y rethinkdb=$RETHINKDBPACKAGEVERSION \ && rm -rf /var/lib/apt/lists/*

VOLUME ["/data"]

WORKDIR /data

CMD ["rethinkdb", "--bind", "all"]

EXPOSE 28015 29015 8080

 

第 1 段(可获 0.75 积分)

第一个FROM是一个很重要的命令,允许你从其他镜像拉取依赖;在这个例子里是Jessive版本的Debian.下一条命令设置了镜像的维护者和引用信息。

RUN命令通常是你使用频率最高的命令。这些定义好的命令都将在容器第一次创建的时候运行。这里面可以写任何你想写的命令,前提是已经有了依赖。例如,你正在使用的一个镜像包含了Ruby的运行时,那么你就可以写如下的Ruby命令。

  • ENV可以在容器里设置环境变量,对一些需要在运行时设置变量的程序很有帮助
  • Volume 定义容器里面暴露给宿主机的路径,也可以在运行时加-v参数来实现
  • WORKDIR 改变容器中的工作目录,以防你需要在某个特定的地方执行某个命令
第 2 段(可获 1.96 积分)

虽然RUN相关的命令用于准备使用容器,CMD运行容器中设计好的需要运行的软件(CMD使用格式["可执行文件", "参数1", "参数2"]),在交互式shell中执行命令它是最好的,例如Python.

能反映Docker微服务结构的,最理想的就是CMD,并且如果需多个CMD,只有最后一个生效.

如果你的容器需要更复杂的东西,可以使用ENTRYPOINT命令,结合CMD传递参数,ENTRYPOINT设置镜像的主命令,如果有这个命令它允许你启动一个镜像.

例如,下面的运行swarm命令,参数是--help:

dockerfile ENTRYPOINT ["/swarm"] CMD ["--help"]

ENTRYPOINT命令的另一个常用用法是在镜像中执行bash脚本,允许更复杂的操作。

第 3 段(可获 1.61 积分)

EXPOSE 展示了软件的使用部分,当使用-p参数运行容器时,帮你将它关联到主机.

从头开始创建 Dockerfile

对于这个例子, 我将创建一个镜像(就是容器)用于测试网站,并用 Jekyll来构建一个网站.我选择Jekyll的原因是所有的网站都用了它,它是一个非常简单的易于理解的网站,当然我也喜爱它.

这里有一个 官方镜像, 但是它并没有使用最新版的Jekyll,(在我看来)它太复杂了,无论如何,我想向你展示如何编写自己的镜像.

第 4 段(可获 1.35 积分)

创建一个新文件夹,里面包含有Dockerfile文件。

从设置一个基础镜像开始,在这里我们使用是官方的Ruby镜像,并且设置了维护者。

#dockerfile 
FROM ruby:latest 
MAINTAINER Name <info@example.com>

现在为Jekyll创建一个用户和用户组,设置适当的权限并且安装Jekyll的gem包:

#dockerfile 
RUN \ 
mkdir -p /home/jekyll && \ 
groupadd -rg 1000 jekyll && \ 
useradd -rg jekyll -u 1000 -d /home/jekyll jekyll && \ 
chown jekyll:jekyll /home/jekyll && \ 
gem install jekyll

我在本地的项目的源文件中工作,因此创建了一个挂载点到Docker容器中使得能够在宿主系统可以访问。

第 5 段(可获 0.91 积分)
dockerfile VOLUME /home/jekyll

你也可以将文件复制到容器中,但是这将使镜像缺少灵活性:

dockerfile COPY . /home/jekyll/

在容器中有些目录是不需要的,所以创建新的.dockerignore文件来忽略这些目录:

dockerfile .bundle .git _site

下一步, 设置包含网站的路径,然后启动网站.

dockerfile WORKDIR /home/jekyll ENTRYPOINT ["jekyll", "serve"] EXPOSE 4000

现在你可以通过如下命令构建镜像:

dockerfile docker build .

执行命令docker run,将会根据修改后的镜像生成容器. 然而, 类似如下的命令将会根据镜像生成容器,设置名称并挂载本地磁盘.你可以通过Docker镜像命令获取IMAGE_ID:

第 6 段(可获 1.31 积分)
bash docker run --name cs_jk -it -d -P -v <PATH_TO_SITE>:/home/jekyll <IMAGE_ID>

到目前为止还不错. 但请记住, 随着 Jekyll 网站的增长, 你还需要在容器中添加gem和其它依赖.让我们来修复它,在 WORKDIR命令行添加下面的内容:

dockerfile COPY Gemfile /home/jekyll COPY Gemfile.lock /home/jekyll RUN bundle install

当你重新构建后,并返回到容器内,此时添加的gem已经变为可用状态.

将镜像推送到Docker Hub

太棒了! 你现在拥有一个自定义的镜像. 接下来就是将它放到Docker Hub,那将对你和其它Docker用户都非常有用.

第 7 段(可获 1.1 积分)

Docker Hub 中注册帐号,然后使用相同的凭证在终端登录:

bash docker login

现在, 为你的镜像打标签:

bash docker tag <IMAGE_ID> <USERNAME>/jekyll:devel

当然, 你也可以自由的将值改变为其它内容.对你来说它可以是任何内容,但这里有一些用户期望的标准标签.现在如果你运行Docker images,最终你可以在存储库那一列上看到可识别的名称.

df_images_with_tag

并把它推送到 Docker Hub:

bash docker push <USERNAME>/jekyll

df_docker_push

如果你登录到 Hub 的帐户中心, 你可以看到列出的镜像,而且其它用户也可以通过 docker pull <USERNAME>/jekyll 命令使用它.

第 8 段(可获 1.19 积分)

df_docker-hub

下一步和最佳实践

 Dockerfile 很简单, 这是故意设计的. Docker的一个核心概念就是让每个组件必须尽可能小和分散,每个容器都能非常完美的执行一个任务。

举个例子,一个Jekyll网站。 可能你也想将代码和错误的文本关联起来,然后创建另一个镜像和容器.想要生成一个ePub的文本?通过Pandoc生成另一个容器.需要在你的网站上搜索? 链接一个Elasticsearch镜像和容器.然后你可以把这些关联起来,并且通过Docker Compose分享代码,它允许你创建复杂的,互联的容器与应用.

第 9 段(可获 1.44 积分)

Dockerfiles是Docker构建工作的基石,离开它们任何工具链都无法工作。虽然它们够简单,但在实践中,为了提供最大的灵活性却很难以一种最好的方式书写它们。想获得更多资讯,我建议参考Docker官方指导,并且我欢迎你提出任何意见或问题。

第 10 段(可获 0.74 积分)

文章评论