编辑注:NGINX Plus Dockerfile(适用于Debian和Alpine Linux)已于2022年12月更新,以适配最新的NGINX Plus版本及相应操作系统发行版的版本。构建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,该ID用于日志文件名;请参阅《管理日志》。
The -p选项指示Docker将NGINX镜像在容器中公开的端口(即端口80)映射到Docker主机上的指定端口。第一个参数指定Docker主机上的端口,第二个参数则映射到容器中公开的端口。
The -d选项指定容器以分离模式运行。这意味着容器会持续运行,直至被停止,但不会响应在命令行中运行的命令。我们将在下一节介绍如何与容器交互。
为验证容器已创建并正在运行,同时查看端口映射,请运行docker ps。(为便于阅读,此处将输出拆分为多行。)
# docker psCONTAINER ID IMAGE COMMAND CREATED ...
fcd1fb01b145 nginx:latest "nginx -g 'daemon of 16 seconds ago ...
... STATUS PORTS NAMES
... Up 15 seconds 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镜像时运行的命令。在COPY文件复制命令中,Dockerfile内指定的本地目录路径是相对于Dockerfile所在的构建上下文而言的。
在本例中,内容位于content目录中,配置文件位于conf目录中。这两个目录都是Dockerfile所在目录的子目录。NGINX镜像包含名为/etc/nginx/nginx.conf和/etc/nginx/conf.d/default.conf的默认NGINX配置文件。由于我们要改用主机中的配置文件,因此添加一条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容器使用mynginx_image2镜像创建一个NGINX容器:
# 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中定义的所有卷都会作为本地目录挂载到该辅助容器中。
参数“debian”表示辅助容器使用Docker Hub中的Debian镜像。由于NGINX镜像也使用Debian(而且目前为止的所有示例都使用NGINX镜像),因此让辅助容器使用Debian效率更高,无需Docker加载其他操作系统。
The /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。此处提供的示例使用Debian 11 (Bullseye)和Alpine Linux 3.17作为基础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官方动态模块的指令(已注释掉)。
By default, no files are copied from the Docker host as a container is created. You can add COPY definitions to each Dockerfile, or the image you create can be used as the basis for another image as described above.
NGINX Plus Dockerfile(Debian 11)
正在加载代码示例…
NGINX Plus Dockerfile(Alpine Linux 3.17)
正在加载代码示例…
创建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=</path/to/your/nginx-repo.crt> --secret id=nginx-key,src=</path/to/your/nginx-repo.key> .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的开源产品和商业产品。
