编辑注:NGINX Plus的Dockerfile(适用于Alpine Linux和Debian)已于2021年11月更新,以采用最新的软件版本。此外,在构建NGINX Plus镜像时,这些Dockerfile和修订后的说明还使用Docker Secret来传递许可证信息。
Docker是一个开放平台,可用于将分布式应用构建、交付并作为容器运行。容器是轻量级、独立且可执行的软件包,包含运行应用所需的一切。容器还可通过Kubernetes等容器编排平台进行部署和编排。(除了本博客介绍的Docker容器技术外,NGINX还提供F5 NGINX Ingress Controller,包括基于NGINX Open Source和基于NGINX Plus的版本;NGINX Plus订阅用户无需额外付费即可获得支持。)
作为软件应用,NGINX Open Source和F5 NGINX Plus都非常适合在Docker中使用。我们还在Docker镜像仓库NGINX Open Source镜像Docker Hub上发布了。本文将介绍如何:
- 部署NGINX Open Source,使用Docker Hub中的镜像
- 管理容器中的NGINX(连接、配置、记录日志、重新加载和重启)
- 部署NGINX Plus,使用您创建的Docker镜像
简介
Docker开放平台包括Docker Engine(用于构建、运行和编排容器的开源运行时)和Docker Hub。Docker Hub是一项托管服务,整个开发者社区或特定组织内部可通过该服务分发、共享Docker化应用并开展协作。
Docker容器将应用与基础设施限制分离,使开发人员能够专注于应用“内容”。Docker化应用可即时移植到任何基础设施,包括笔记本电脑、裸机服务器、虚拟机或云环境,从而成为可轻松组装和重新组装的模块化组件,用于构建功能完备的分布式应用,并持续进行实时创新。
有关Docker的更多信息,请参阅为什么选择Docker?或完整的Docker文档。
使用NGINX Open Source Docker镜像
可以使用来自Docker Hub的NGINX Open Source镜像在Docker容器中创建NGINX实例。
先来看一个非常简单的示例。要启动一个在容器中运行并使用默认NGINX配置的NGINX实例,请运行以下命令:
# docker run --name mynginx1 -p 80:80 -d nginxfcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d此命令基于NGINX镜像创建一个名为mynginx1的容器。该命令会返回完整的容器ID,用于日志文件的命名;请参阅管理日志。
The -p选项指示Docker将NGINX镜像在容器中公开的端口(即端口80)映射到Docker主机上的指定端口。第一个参数指定Docker主机上的端口,第二个参数则映射到容器中公开的端口。
The -d选项指定容器以分离模式运行。这意味着容器会持续运行,直至被停止,但不会响应在命令行中运行的命令。下一节将介绍如何与容器交互。
要验证容器是否已创建并正在运行,并查看端口映射,请运行docker ps。(为便于阅读,此处将输出拆分为多行。)
# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS ...
fcd1fb01b145 nginx:latest "nginx -g 'daemon of 16 seconds ago Up 15 seconds ...
... PORTS NAMES
... 0.0.0.0:80->80/tcp mynginx1输出中的PORTS字段显示,Docker主机上的端口 80 已映射到容器中的端口 80。还可以通过向该端口发出HTTP请求来验证NGINX是否正在运行。随后会显示默认NGINX欢迎页面的代码:
# curl http://localhost<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="https://www.nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>使用NGINX Docker容器
现在,NGINX Docker容器已经可以正常运行,但该如何管理内容和NGINX配置?日志记录又该如何处理?
关于SSH的说明
通常会为NGINX实例启用SSH访问,但NGINX镜像未安装OpenSSH,因为Docker容器通常仅用于单一用途(在本例中为运行NGINX)。因此,我们将改用Docker支持的其他方法。
除了使用以下命令外,还可以运行下面的命令,为正在运行的NGINX容器打开交互式shell(而不是启动SSH会话)。不过,仅建议高级用户采用这种方式。
- 在Alpine Linux系统上:
# docker exec -it NGINX_container_ID sh- 在Debian系统上:
# docker exec -it NGINX_container_ID bash管理内容和配置文件
可以通过多种方式管理NGINX提供的内容和NGINX配置文件。下面介绍其中几种方式。
选项 1:在 Docker 主机上维护内容和配置
创建容器时,可以让Docker将Docker主机上的本地目录挂载到容器中的目录。NGINX镜像使用默认的NGINX配置,其中以/usr/share/nginx/html作为容器的根目录,并将配置文件放在/etc/nginx中。假设Docker主机的内容位于本地目录/var/www中,配置文件位于/var/nginx/conf中,请运行以下命令(此处仅为便于阅读而分多行显示):
# docker run --name mynginx2 --mount type=bind source=/var/www,target=/usr/share/nginx/html,readonly --mount type=bind,source=/var/nginx/conf,target=/etc/nginx/conf,readonly -p 80:80 -d nginx现在,对Docker主机上本地目录/var/www和/var/nginx/conf中文件所做的任何更改,都会反映到容器内的目录/usr/share/nginx/html和/etc/nginx中。readonly选项表示这些目录只能在Docker主机上更改,不能从容器内更改。
选项 2:从 Docker 主机复制文件
另一种方法是在创建容器时,让Docker从Docker主机上的本地目录复制内容和配置文件。容器创建后,如果文件发生更改,可以创建新容器或直接修改容器中的文件来维护这些文件。复制文件的一种简单方法是创建一个Dockerfile,其中包含基于Docker Hub中的NGINX镜像生成新Docker镜像时运行的命令。对于Dockerfile中的文件复制(COPY)命令,本地目录路径是相对于Dockerfile所在的构建上下文而言的。
在本例中,内容位于content目录中,配置文件位于conf目录中。这两个目录都是Dockerfile所在目录的子目录。NGINX镜像包含以下默认NGINX配置文件:/etc/nginx/nginx.conf和/etc/nginx/conf.d/default.conf。由于我们希望改用主机中的配置文件,因此添加一条RUN命令来删除默认文件:
FROM nginx
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx在Dockerfile所在目录中运行以下命令,创建自定义NGINX镜像。请注意命令末尾的句点(“.”)。该句点将当前目录指定为构建上下文,其中包含Dockerfile以及要复制的目录。
# docker build -t mynginx_image1 .现在运行以下命令,创建一个名为mynginx3的容器,该容器基于mynginx_image1镜像:
# docker run --name mynginx3 -p 80:80 -d mynginx_image1如果要修改容器中的文件,请按照选项 3 中的说明使用辅助容器。
选项3:维护容器中的文件
如关于SSH的说明中所述,我们无法使用SSH访问NGINX容器。因此,如果要直接编辑内容文件或配置文件,就必须创建一个可通过shell访问的辅助容器。要让辅助容器访问这些文件,必须创建一个新镜像,并为该镜像正确定义Docker数据卷。假设要像选项2一样复制文件,同时定义卷,可使用以下Dockerfile:
FROM nginxRUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /usr/share/nginx/html
VOLUME /etc/nginx然后,运行以下命令创建新的NGINX镜像(同样请注意末尾的句点):
# docker build -t mynginx_image2 .现在运行以下命令,基于mynginx4镜像创建一个NGINX容器(mynginx_image2):
# docker run --name mynginx4 -p 80:80 -d mynginx_image2然后运行以下命令,启动一个带有shell的辅助容器mynginx4_files,以便访问刚刚创建的mynginx4容器中的内容目录和配置目录:
# docker run -i -t --volumes-from mynginx4 --name mynginx4_files debian /bin/bashroot@b1cbbad63dd1:/#新的mynginx4_files辅助容器在前台运行,并保持标准输入持续打开(使用-i选项),同时分配一个tty(使用-t选项)。在mynginx4中定义的所有卷都会作为本地目录挂载到该辅助容器中。
The debian 参数表示辅助容器使用Docker Hub中的Debian镜像。由于NGINX镜像也使用Debian(而且目前为止的所有示例都使用NGINX镜像),因此让辅助容器使用Debian效率更高,无需Docker加载其他操作系统。/bin/bash 参数表示在辅助容器中运行 bash shell,并显示shell提示符,以便根据需要修改文件。
要启动和停止容器,请运行以下命令:
# docker start mynginx4_files# docker stop mynginx4_files要退出shell但让容器继续运行,请按Ctrl+p,然后按Ctrl+q。要重新访问正在运行的容器的shell,请运行以下命令:
# docker attach mynginx4_files要退出shell并终止容器,请运行exit命令。
管理日志记录
您可以配置默认日志记录或自定义日志记录。
使用默认日志记录
默认情况下,NGINX镜像配置为将主要的NGINX访问日志和错误日志发送到Docker日志收集器。具体做法是分别将这两类日志链接到stdout和stderr;随后,这两类日志中的所有消息都会写入Docker主机上的文件/var/lib/docker/containers/container-ID/container-ID-json.log,其中container‑ID是创建容器时返回的长格式ID。例如,对于我们在使用NGINX Open Source Docker镜像中创建的初始容器,其ID为fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d。
要获取现有容器的容器ID,请运行以下命令。其中,container‑name是创建容器时通过--name参数设置的值(例如,对于上述容器ID,该值为mynginx1):
# docker inspect --format '{{ .Id }}' container-name虽然可以直接打开container-ID-json.log文件查看日志,但运行以下命令通常更方便:
# docker logs container-name还可以使用Docker Engine API提取日志消息,方法是向Docker Unix套接字发送GET请求。此命令会同时返回访问日志(以stdout=1表示)和错误日志(以stderr=1表示),也可以单独请求其中任一日志:
curl --unix-socket /var/run/docker-sock http://localhost/containers/container-name/logs?stdout=1&stderr=1要了解其他查询参数,请参阅Docker Engine API 文档(在该页面中搜索“Get container logs”)。
使用自定义日志记录
如果要采用其他日志收集方法,或要在某些配置块(例如server{}和location{})中以不同方式配置日志,请为容器内用于存储日志文件的一个或多个目录定义Docker卷,创建一个辅助容器来访问日志文件,并使用所需的日志记录工具。为此,请创建一个包含日志文件所用卷的新镜像。
例如,要将NGINX配置为在/var/log/nginx/log中存储日志文件,可以从Dockerfile(参见选项3)入手,只需为此目录添加VOLUME定义:
FROM nginxRUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /var/log/nginx/log然后,可以按上述说明创建镜像,并使用该镜像创建一个NGINX容器和一个可访问日志目录的辅助容器。辅助容器中可以安装所需的任何日志记录工具。
控制NGINX
由于无法直接访问NGINX容器的命令行,因此不能使用nginx命令控制NGINX。所幸,可以使用信号控制NGINX,而Docker提供了kill命令,用于向容器发送信号。
要重新加载NGINX配置,请运行以下命令:
# docker kill -s HUP container-name要重启NGINX,请运行以下命令来重启容器:
# docker restart container-name使用Docker部署NGINX Plus
到目前为止,我们讨论了如何将Docker用于NGINX Open Source,但Docker也可与商业产品NGINX Plus配合使用。不同之处在于,您首先需要创建NGINX Plus镜像,因为NGINX Plus是商业产品,无法从Docker Hub获取。好在创建镜像非常简单。
注意:切勿将NGINX Plus镜像上传到Docker Hub等公共存储库。这样做会违反许可协议。
创建NGINX Plus Docker镜像
要生成NGINX Plus镜像,请先创建一个Dockerfile。此处提供的示例使用Alpine Linux 3.14和Debian 11(Bullseye)作为Docker基础镜像。创建NGINX Plus Docker镜像之前,必须下载与所用版本对应的nginx-repo.crt和nginx-repo.key文件。NGINX Plus客户可在客户门户中找到这些文件;如果正在免费试用NGINX Plus,这些文件已随试用包提供。请将这些文件复制到Dockerfile所在的目录(Docker构建上下文)中。
与NGINX Open Source一样,默认情况下,NGINX Plus访问日志和错误日志会链接到Docker日志收集器。此处未指定卷,但可根据需要添加;也可以使用每个Dockerfile创建基础镜像,再基于这些基础镜像创建指定了卷的新镜像,如前文所述。
我们特意未在示例Dockerfile中指定NGINX Plus版本,因此更新到NGINX Plus的新版本时,无需编辑该文件。不过,我们提供了相关指令的注释版本。如果希望该文件仅适用于特定版本,可以取消这些指令的注释。
同样,我们还提供了用于安装NGINX Plus官方动态模块的指令(已注释掉)。
默认情况下,创建容器时不会从Docker主机复制任何文件。可以向每个COPYDockerfile中添加定义,也可以按照上述说明,将创建的镜像用作其他镜像的基础。
NGINX Plus Dockerfile(Debian 11)
正在加载代码示例…
NGINX Plus Dockerfile(Alpine Linux 3.14)
正在加载代码示例…
创建NGINX Plus镜像
将Dockerfile、nginx-repo.crt和nginx-repo.key文件放在同一目录中,然后在该目录中运行以下命令,创建名为nginxplus的Docker镜像(与之前一样,请注意末尾的句点):
# DOCKER_BUILDKIT=1 docker build --no-cache -t nginxplus --secret id=nginx-crt,src=your_cert_file --secret id=nginx-key,src=your_key_file .The DOCKER_BUILDKIT=1标志表示使用Docker BuildKit构建镜像;添加下文所述的--secret选项时,必须使用该工具。
The --no-cache选项指示Docker从头开始构建镜像,并确保安装最新版本的NGINX Plus。如果此前曾使用Dockerfile构建镜像,但未添加--no-cache选项,则新镜像会使用Docker缓存中的NGINX Plus版本。(如前所述,我们特意未在Dockerfile中指定NGINX Plus版本,因此无需在NGINX Plus每次发布新版本时更改该文件。)如果可以接受使用此前所构建镜像中的NGINX Plus版本,则可省略--no-cache选项。
The --secret选项会将NGINX Plus许可证的证书和密钥传递到Docker构建上下文,同时避免数据泄露或在Docker构建层之间持久保留。若不修改基础id参数的值,则无法更改Dockerfile,但需要将src参数设置为NGINX Plus证书和密钥文件的路径(如果已按照前述说明操作,即构建Docker镜像的同一目录)。
执行docker images nginxplus 命令后,如果显示类似以下内容,则表示镜像已成功创建:
# docker images nginxplus
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
nginxplus latest ef2bf65931cf 6 seconds ago 91.2 MB要基于此镜像创建名为“mynginxplus”的容器,请运行以下命令:
# docker run --name mynginxplus -p 80:80 -d nginxplus可以像控制和管理NGINX Open Source容器一样控制和管理NGINX Plus容器。
总结
NGINX、NGINX Plus和Docker可以高效协同工作。无论是使用Docker Hub上的NGINX Open Source镜像,还是自行创建NGINX Plus镜像,都可以轻松在Docker容器中启动新的NGINX和NGINX Plus实例,并将其部署到Kubernetes环境中。还可以基于基础镜像轻松创建新的Docker镜像,让容器更易于控制和管理。请确保Docker容器中运行的所有NGINX Plus实例均在订阅涵盖范围内。有关详细信息,请联系NGINX销售团队。
Docker涉及的内容远不止本文所能涵盖。要了解更多信息,请下载我们的免费O’Reilly电子书《容器网络:从Docker到Kubernetes》,或访问www.docker.com。
相关文档
关于作者

相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
