Docker 教程(二):Dockerfile-阿里云开发者社区

开发者社区> 看山灬> 正文

Docker 教程(二):Dockerfile

简介: Dockerfile包含一组关于如何构建Docker镜像的说明,通过docker build命令执行Dockerfile文件,可以构建一个Docker镜像,本文介绍了如何编写Dockerfile文件以及构建一个Docker镜像。
+关注继续查看

image.png

你好,我是看山。


本文源自并发编程网的翻译邀请,翻译的是 Jakob Jenkov 的 《Docker 教程》 中的第二篇。


Dockerfile包含一组关于如何构建Docker镜像的说明,通过docker build命令执行Dockerfile文件,可以构建一个Docker镜像,本文介绍了如何编写Dockerfile文件以及构建一个Docker镜像。


Dockerfile的好处

Dockerfile文件以书面形式说明了如何构建一个Docker镜像,Docker镜像通常包含如下内容:


首先需要一个基本的Docker镜像,在这个基础Docker镜像上构建自己的Docker镜像。

一组需要安装在Docker镜像中的工具和应用。

一组需要复制到Docker镜像中的文件(比如配置文件)。

可能需要在防火墙中打开的网络(TPC/UDP)端口或其他。

等等。。。

首先,在Dockerfile文件中以书面形式说明这些,就意味着,我们不用特意记住应用程序如何安装,包括操作系统什么要求、需要安装的应用程序、需要赋值的文件、需要打开的网络端口等,这些内容都被记录在Dockerfile中。


另外,通过Dockerfile文件构建Docker镜像,我们不需要手动执行这些繁琐重复且容易出错的工作。Docker会自动做这些事情,简单、快速、且不容易出错。


第三,我们很容易和其他人分享Dockerfile文件,并且他们可以自己构建Docker镜像。


第四,Dockerfile很容易存储在Git这样的版本控制器中,这样就可以跟踪Dockerfile(服务器、应用配置)的变更记录。版本控制器也可以很容易的让人们协同合作,比如在Dockerfile上,以及分享Dockerfile。


Dockerfile的结构

Dockerfile包含一组指令,每个指令有一个命令和参数组成,类似于命令行可执行文件。下面是一个Dockerfile简单示例:


# 基础镜像
FROM ubuntu:latest

# 这里可以有更多安装软件和复制文件到镜像中的说明。
COPY    /myapp/target/myapp.jar    /myapp/myapp.jar

# 在Docker容器中执行的命令。
CMD echo Starting Docker Container

Docker基础镜像

Docker镜像是由层组成,每一层都会为最终的Docker镜像添加一些内容。每一个层实际上都是一个单独的Docker镜像,所以说,Docker镜像是由一个或多个层镜像组成,我们可以在其上添加自己的层。


当通过Dockerfile文件指定自己的Docker镜像时,通常是从一个Docker基础镜像开始。这是另一个Docker镜像,可以在其上构建自己的Docker镜像。这个Docker基础镜像本身可能也包含多个层,并且是基于另一个基础镜像构建的。


我们可以使用From命令在Dockerfile文件中指定Docker镜像作为基础镜像,如下节所述。


MAINTAINER

MAINTAINER命令用于说明谁在维护这个Dockerfile文件。比如:


MAINTAINER   Joe Blocks <joe@blocks.com>

MAINTAINER命令并不常用,因为这类信息在Git存储或其他地方有了。


FROM

FROM命令用于指定Docker基础镜像,如果是从原始Linux镜像开始,可以使用如下命令:


# 基础镜像
FROM ubuntu:latest

CMD

CMD命令用于指定启动Docker容器是需要执行的命令,该容器是基于此Dockerfile构建的Docker镜像,下面是一些Dockerfile的CMD示例:


CMD echo Docker container started.

本例是打印“Docker container started”这行文本。


下一个CMD示例是启动一个java应用:


CMD java -cp /myapp/myapp.jar com.jenkov.myapp.MainClass arg1 arg2 arg3

COPY

COPY命令将一个或多个文件从主机(从Dockerfile文件构建Docker镜像的机器)复制到Docker镜像中,可以复制的内容包括文件或目录,下面是一个示例:


COPY    /myapp/target/myapp.jar    /myapp/myapp.jar

这个例子是把主机的/myapp/target/myapp.jar文件复制到Docker进行中的/myapp/myapp.jar文件。第一个参数是主机路径(从哪里来),第二个参数是Docker镜像的路径(到哪里去)。


我们还可以复制一个目录到Docker镜像中,比如:


COPY    /myapp/config/prod    /myapp/config

这个例子是把主机的/myapp/config/prod目录复制到Docker镜像中的/myapp/config目录。


我们还可以复制多个文件到Docker镜像中的一个目录中,比如:


COPY    /myapp/config/prod/conf1.cfg   /myapp/config/prod/conf2.cfg   /myapp/config/

这个例子是将主机的/myapp/config/prod/conf1.cfg文件和/myapp/conig/prod/conf2.cfg文件复制到Docker镜像中的/myapp/config/目录中。注意,目标目录必须以/(斜杠)结束才能工作。


ADD

ADD命令与COPY命令工作方式相同,只有一些细微的差别:


ADD命令可以复制并提取TAR文件到Docker镜像中。

ADD命令可以通过HTTP下载文件,并复制到Docker镜像中。

下是一些示例:


ADD    myapp.tar    /myapp/

这个例子是将指定的TAR文件解压缩并提取到Docker镜像的/myapp/目录中。


下面是另一个例子:


ADD    http://jenkov.com/myapp.jar    /myapp/

ENV

ENV命令是在Docker镜像中设置环境变量,此环境变量可用于CMD命令在Docker镜像内部启动应用程序。举个例子:


ENV    MY_VAR   123

本例将环境变量MY_VAR设置为值123。


RUN

RUN可以在Docker镜像中执行命令行指令,执行时机是Docker镜像构建过程中,所以RUN命令只会执行一次。RUN命令可用于在Docker镜像中安装应用程序、提取文件或其他命令行功能,这些操作只需要执行一次,以供Docker镜像后续使用。


RUN apt-get install some-needed-app

ARG

ARG命令允许定义一个参数,这个参数可以在通过Dockerfile文件构建Docker镜像时,通过命令参数传递给Docker。比如:

ARG tcpPort

当执行docker build命令执行Dockerfile构建Docker镜像时,可以指定tcpPort参数,比如:

docker build --build-arg tcpPort=8080 .

注意,--build-arg后面的tcpPort=8080,是将tcpPort参数的值设置为8080。


我们可以通过多个ARG命令定义多个参数,举个例子:


ARG tcpPort
ARG useTls

当构建Docker镜像时,必须为所有构建参数提供值。【译者注,1.13版本之前,不提供值会直接报错,1.13版本之后,不提供值不会报错,但是会弹出警告】。举个例子:


docker build --build-arg tcpPort=8080 --build-arg useTls=true .

我们可以为ARG设置默认值,当构建Docker镜像时,如果没有指定参数值,将使用默认值。举个例子:

ARG tcpPort=8080
ARG useTls=true

如果tcpPort和useTls在生成Docker镜像时,都没有设置参数,将使用默认值8080和true。


ARG声明的参数通常在Dockerfile的其他地方引用,比如:


ARG tcpPort=8080
ARG useTls=true

CMD start-my-server.sh -port ${tcpPort} -tls ${useTls}

注意:两个引用${tcpPort}和${useTls},引用名是tcpPort和useTls这两个ARG声明的参数。


docker build --build-arg tcpPort=8080

WORKDIR

WORKDIR命令指明了Docker镜像中的工作目录,工作目录将对WORKDIR指令之后的所有命令生效,举个例子:


WORKDIR    /java/jdk/bin

EXPOSE

EXPOSE命令将对外开放Docker容器中的网络端口,比如,如果Docker容器运行一个web服务器,那么,该web服务器可能需要打开端口80,以便客户端链接到它。举个例子:


EXPOSE   8080

我们还可以指明打开端口的通信协议,比如:UDP和TCP。下面是设置允许通信协议的示例:


EXPOSE   8080/tcp 9999/udp

如果没有指定协议,将默认认定为TCP协议。


VOLUME

VOLUME命令会在Docker镜像中创建一个目录,这个目录可以挂载到Docker主机上。换句话说,可以在Docker镜像中创建目录,比如/data,这个目录可以在稍后挂载到Docker主机的/container-data/container1目录上。挂载成功后,容器会启动。下面是一个使用VOLUME命令在Dockerfile中定义装载目录的示例:


VOLUME   /data

ENTRYPOINT

ENTRYPOINT命令为从该Docker镜像启动Docker容器提供入口点,入口点是Docker容器启动时执行的应用程序或命令。这样,ENTRYPOINT和CMD工作方式类似,不同之处在于,使用ENTRYPOINT时,当ENTRYPOINT执行的应用程序完成时,Docker容器将关闭。因此,ENTRYPOINT使Docker镜像本身成为一个可执行命令,可以启动,完成后关闭。以下是ENTRYPOINT示例:


ENTRYPOINT java -cp /apps/myapp/myapp.jar com.jenkov.myapp.Main

这个示例将在容器启动时执行Java应用程序的主类com.jenkov.myapp.Main,当应用程序关闭时,Docker容器也会关闭。


HEALTHCHECK

HEALTHCHECK命令可以定期执行健康检查,以监视Docker容器中运行的应用程序的运行状况。如果命令返回0,Docker将认为应用程序和容器正常,如果命令返回1,Docker会认为应用程序和容器不正常。示例如下:


HEALTHCHECK java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

这个示例中使用了java应用程序的com.jenkov.myapp.HealthCheck作为健康检查的命令,我们可以使用任何有意义的健康检查命令。


健康检查间隔时间

默认情况下,Docker每30秒执行一次HEALTHCHECK命令。如果想修改时间间隔,我们可以自定义时间,通过--interval参数,可以指定健康检查的检查间隔时间。下面是一个将HEALTHCHECK间隔设置为60秒的示例:


HEALTHCHECK --interval=60s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

健康检查开始时间

默认情况下,Docker会立即检查Docker容器的监控状况。但是,有些应用程序可能需要一段时间启动,因此,只有经过某段时间后再进行健康检查才有意义。我们可以使用--start-period参数设置健康检查开始时间。下面是一个将健康检查设置为5分钟的示例,在Docker开始健康检查之前,为容器和应用程序提供300秒(5分钟)的启动时间:


HEALTHCHECK --start-period=300s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

健康检查超时时间

健康检查很有可能超时,如果HEALTCHECK命令需要超过给定时间限制才完成,Docker将认为健康检查超时。可以使用--timeout参数设置超时时间,如下是设置超时时间为5秒的示例:


HEALTHCHECK --timeout=5s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

注意,如果健康检查超时,Docker也会认为容器不健康。


健康检查重复次数

如果HEALTHCHECK命令执行失败,有可能是结果返回1,或者执行超时,Docker会在认定容器不健康前,重试3次HEALTHCHECK命令,用于检查Docker容器是否返回健康状态。可以通过--retries设置重试次数。下面是将重试次数设置为5的示例:


HEALTHCHECK --retries=5 java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

推荐阅读

Docker 教程(一):Docker 是什么

Docker 教程(二):Dockerfile

Docker 教程(三):Docker 命令


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10062 0
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
26784 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11605 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
9157 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13875 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
4498 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7361 0
+关注
看山灬
专注后端开发、架构相关知识分享,个人网站 https://howardliu.cn/。
136
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载