博客 | NGINX

使用 Docker 部署 NGINX 和 NGINX Plus

NGINX-F5-horiz-black-type-RGB 的一部分
里克·尼尔森缩略图
里克·尼尔森
2021 年 11 月 9 日发布


编辑器– Alpine Linux 和 Debian 的 NGINX Plus Dockerfiles于 2021 年 11 月更新,以反映最新的软件版本。 他们还(连同修订后的说明)在构建 NGINX Plus 映像时使用 Docker 机密来传递许可证信息。

Docker是一个开放平台,用于以容器(轻量级、独立、可执行的软件包,包含运行应用所需的一切)的形式构建、运送和运行分布式应用。 容器又可以通过Kubernetes等容器编排平台进行部署和编排。 (除了本博客中讨论的 Docker 容器技术之外,NGINX 还在基于 NGINX 开源版本和基于 NGINX Plus 版本中提供了F5 NGINX Ingress Controller ;对于 NGINX Plus 订阅者,可免费获得支持。)

作为软件应用, NGINX Open SourceF5 NGINX Plus是 Docker 的绝佳用例,我们在 Docker 镜像存储库Docker Hub上发布了NGINX Open Source 镜像。 这篇文章解释了如何:

介绍

Docker 开放平台包括 Docker Engine(构建、运行和编排容器的开源运行时)和 Docker Hub(一项托管服务,整个开发社区或特定组织范围内可在该服务上分发、共享和协作 Dockerized应用)。

Docker 容器将应用与基础设施的限制分离,使开发人员能够将精力集中在应用“内容”上。 Docker 化的应用可以立即移植到任何基础设施 - 笔记本电脑、裸机服务器、虚拟机或云 - 使其成为模块化组件,可以轻松组装和重新组装成功能齐全的分布式应用,并不断实时创新。

有关 Docker 的更多信息,请参阅为什么选择 Docker?或完整的Docker 文档

使用 NGINX 开源 Docker 镜像

您可以使用来自 Docker Hub 的NGINX 开源映像在 Docker 容器中创建 NGINX 实例。

让我们从一个非常简单的例子开始。 要启动在容器中运行并使用默认 NGINX 配置的 NGINX 实例,请运行以下命令:

#docker 运行--名称 mynginx1-p 80:80-d nginx fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d

此命令基于 NGINX 镜像创建一个名为mynginx1的容器。 该命令返回容器 ID 的长格式,该 ID 用于日志文件的名称;请参阅管理日志记录

-p选项告诉 Docker 将 NGINX 镜像在容器中公开的端口(端口 80)映射到 Docker 主机上的指定端口。 第一个参数指定Docker主机中的端口,而第二个参数映射到容器中暴露的端口。

-d选项指定容器以分离模式运行,这意味着它会继续运行直到停止,但不会响应在命令行上运行的命令。 在下一节中我们将解释如何与容器交互。

为了验证容器是否已创建并正在运行,以及查看端口映射,我们运行docker ps 。 (我们在这里将输出分成多行,以使其更易于阅读。)

# docker ps容器 ID 镜像命令创建状态... fcd1fb01b145 nginx:latest “nginx -g '16 秒前启动的守护进程 15 秒... ... 港口名称... 0.0.0.0:80->80/tcp mynginx1

输出中的PORTS字段报告 Docker 主机上的端口 80 已映射到容器中的端口 80。 验证 NGINX 是否正在运行的另一种方法是向该端口发出 HTTP 请求。 默认 NGINX 欢迎页面的代码如下:

# curl http://localhost<!DOCTYPE html>
<html>
<head>
<title>欢迎使用 nginx!</title>
<style>
body {
width: 35em;边距: 0 自动;字体系列: Tahoma, Verdana, Arial, sans-serif; } 需要进一步配置。

使用 NGINX Docker 容器

现在我们有一个可以运行的 NGINX Docker 容器,但是我们如何管理其内容和 NGINX 配置呢? 那么日志记录又如何呢?

关于 SSH 的说明

启用 SSH 访问 NGINX 实例是很常见的,但 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中。 对于内容位于本地目录/var/www且配置文件位于/var/nginx/conf的 Docker 主机,运行此命令(此处显示为多行仅为了便于阅读):

# docker run --name mynginx2 --mount 类型=bind 源=/var/www,target=/usr/share/nginx/html,readonly --mount 类型=bind,源=/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命令:

来自 nginx
运行 rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
复制内容 /usr/share/nginx/html
复制 conf /etc/nginx

我们从Dockerfile所在的目录运行以下命令来创建我们自己的 NGINX 镜像。 请注意命令末尾的句点(“.”。)。 它将当前目录定义为构建上下文,其中包含Dockerfile和要复制的目录。

#docker build-t mynginx_image1。

现在我们运行此命令基于mynginx_image1镜像创建一个名为mynginx3的容器:

#docker run--name mynginx3-p 80:80-d mynginx_image1

如果我们想更改容器中的文件,我们可以用选项 3 中描述的辅助容器。

选项 3——维护容器中的文件

正如在关于 SSH 的注意事项中提到的,我们不能使用 SSH 访问 NGINX 容器,所以如果我们想直接编辑内容或配置文件,我们必须创建一个具有 shell 访问权限的辅助容器。 为了使辅助容器能够访问这些文件,我们必须创建一个新镜像,并为该镜像定义适当的Docker 数据卷。 假设我们想要按照选项 2 复制文件,同时定义卷,我们使用以下Dockerfile

从 nginx 运行 rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
复制内容 /usr/share/nginx/html
复制 conf /etc/nginx
卷 /usr/share/nginx/html
卷 /etc/nginx

然后,我们通过运行以下命令来创建新的 NGINX 映像(再次注意最后的句点):

#docker build -t mynginx_image2。

现在我们运行此命令基于mynginx_image2映像创建一个 NGINX 容器( mynginx4 ):

#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/bash root@b1cbbad63dd1:/#

新的mynginx4_files辅助容器在前台运行,带有持久标准输入( -i选项)和 tty( -t选项)。 mynginx4中定义的所有卷都作为本地目录挂载在辅助容器中。

debian参数意味着辅助容器使用来自 Docker Hub 的 Debian 映像。 因为 NGINX 镜像也使用 Debian(并且我们迄今为止的所有示例都使用 NGINX 镜像),所以使用 Debian 作为辅助容器是最有效的,而不是让 Docker 加载另一个操作系统。 /bin/bash参数意味着bash shell 在辅助容器中运行,显示一个 shell 提示符,您可以使用它来根据需要修改文件。

要启动和停止容器,请运行以下命令:

#docker启动 mynginx4_files #docker停止 mynginx4_files

要退出 shell 但保持容器运行,请按Ctrl+p ,然后按Ctrl+q 。 要重新获得正在运行的容器的 shell 访问权限,请运行以下命令:

#docker附加 mynginx4_files

要退出 shell 并终止容器,请运行exit命令。

管理日志

您可以配置默认或自定义日志记录。

使用默认日志记录

NGINX 镜像默认配置为将主要 NGINX 访问和错误日志发送到 Docker 日志收集器。 这是通过将它们分别链接到stdoutstderr来实现的;然后,两个日志中的所有消息都被写入 Docker 主机上的文件/var/lib/docker/containers/container-ID/container-ID-json.log 其中, container-ID是创建容器时返回的长格式 ID。 例如,在使用 NGINX 开源 Docker 镜像中创建的初始容器是fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d

要检索现有容器的容器 ID,请运行此命令,其中container‑name是创建容器时由--name参数设置的值(例如,对于上面的容器 ID,它是mynginx1 ):

# docker inspect --format '{{ .Id }}'容器名称

虽然您可以通过直接打开container-ID -json.log文件来查看日志,但运行此命令通常更容易:

#docker logs容器名称

您还可以使用Docker Engine API来提取日志消息,通过向 Docker Unix 套接字发出GET请求。 此命令返回访问日志(由stdout=1表示)和错误日志( stderr=1表示),但您也可以单独请求它们:

curl --unix-socket /var/run/docker-sock http://localhost/containers/容器名称/logs?stdout=1&stderr=1

要了解其他查询参数,请参阅Docker Engine API 文档(在该页面上搜索“获取容器日志”)。

使用自定义日志记录

如果您想要实现另一种日志收集方法,或者想要在某些配置块(例如server{}location{} )中以不同的方式配置日志记录,请为用于在容器中存储日志文件的目录定义一个 Docker 卷,创建一个辅助容器来访问日志文件,并使用您喜欢的任何日志记录工具。 为了实现这一点,请创建一个包含日志文件的卷或多个卷的新映像。

例如,要配置 NGINX 以将日志文件存储在/var/log/nginx/log中,我们可以从选项 3 中Dockerfile开始,然后简单地为该目录添加一个VOLUME定义:

从 nginx 运行 rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
复制内容 /usr/share/nginx/html
复制 conf /etc/nginx
卷 /var/log/nginx/log

然后,我们可以按照上面描述的方式创建一个图像,并使用它来创建可以访问日志目录的 NGINX 容器和辅助容器。 辅助容器可以安装任何所需的日志记录工具。

控制NGINX

由于我们无法直接访问 NGINX 容器的命令行,因此我们无法使用nginx命令来控制 NGINX。幸运的是,我们可以使用信号来控制 NGINX,Docker 提供了kill命令来向容器发送信号。

要重新加载 NGINX 配置,请运行以下命令:

# docker kill -s HUP容器名称

要重新启动 NGINX,请运行以下命令重新启动容器:

#docker restart容器名称

使用 Docker 部署 NGINX Plus

到目前为止,我们已经讨论了用于 NGINX 开源的 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.crtnginx-repo.key文件。 NGINX Plus 客户可以在客户门户上找到它们;如果您正在免费试用 NGINX Plus,它们将随您的试用包一起提供。 将文件复制到Dockerfile所在的目录(Docker 构建上下文)。

与 NGINX Open Source 一样,默认情况下 NGINX Plus 访问和错误日志链接到 Docker 日志收集器。 没有指定卷,但您可以根据需要添加它们,或者每个Dockerfile都可以用于创建基础映像,您可以从中创建具有指定卷的新映像,如前所述。

我们特意没有在示例Dockerfiles中指定 NGINX Plus 版本,这样您在更新到 NGINX Plus 的新版本时不必编辑该文件。 但是,如果您想使文件版本特定,我们已经包含了相关说明的注释版本,供您取消注释。

类似地,我们还提供了安装NGINX Plus 官方动态模块的说明(已注释掉)。

默认情况下,创建容器时不会从 Docker 主机复制任何文件。 您可以向每个Dockerfile添加COPY定义,或者您创建的镜像可以作为另一个镜像的基础,如上所述。

NGINX Plus Dockerfile(Debian 11)

NGINX Plus Dockerfile(Alpine Linux 3.14)

创建 NGINX Plus 镜像

Dockerfilenginx-repo.crtnginx-repo.key文件放在同一目录中,在那里运行以下命令来创建一个名为nginxplus的 Docker 镜像(与前面一样,注意最后的句点):

# DOCKER_BUILDKIT=1 docker build --no-cache -t nginxplus --secret id=nginx-crt,src=你的证书文件--secret id=nginx-key,src=你的密钥文件

DOCKER_BUILDKIT=1标志表示我们正在使用Docker BuildKit来构建镜像,这是包含下面讨论的--secret选项时所必需的。

--no-cache选项告诉 Docker 从头开始构建映像并确保安装最新版本的 NGINX Plus。 如果之前使用Dockerfile构建镜像并且未包含--no-cache选项,则新镜像将使用 Docker 缓存中的 NGINX Plus 版本。 (如上所述,我们故意不在Dockerfile中指定 NGINX Plus 版本,这样该文件就不需要在每次发布 NGINX Plus 新版本时进行更改。) 如果可以使用先前构建的图像中的 NGINX Plus 版本,请省略--no-cache选项

--secret选项将您的 NGINX Plus 许可证的证书和密钥传递给 Docker 构建上下文,而不会冒着暴露数据的风险或让数据在 Docker 构建层之间持续存在。 不改变基本Dockerfile就无法更改id参数的值,但您需要将src参数设置为 NGINX Plus 证书和密钥文件的路径(如果您按照前面的说明操作,则与您构建 Docker 镜像的目录相同)。

docker images nginxplus命令的输出如下,表明镜像创建成功:

#docker 镜像 nginxplus存储库标签 镜像 ID 创建 虚拟大小 nginxplus 最新 ef2bf65931cf 6 秒前 91.2 MB

要基于此映像创建名为mynginxplus的容器,请运行以下命令:

#docker run--name mynginxplus-p 80:80-d nginxplus

您可以采用与 NGINX 开源容器相同的方式控制和管理 NGINX Plus 容器。

概括

NGINX、NGINX Plus 和 Docker 协同工作效果极佳。 无论您使用来自 Docker Hub 的 NGINX 开源镜像还是创建自己的 NGINX Plus 镜像,您都可以轻松地在 Docker 容器中启动 NGINX 和 NGINX Plus 的新实例,并将其部署在您的 Kubernetes 环境中。 您还可以轻松地从基础镜像创建新的 Docker 镜像,从而使您的容器更易于控制和管理。 确保您的订阅涵盖 Docker 容器中运行的所有 NGINX Plus 实例。 有关详细信息,请联系 NGINX 销售团队

Docker 的内容远比我们在本文中介绍的要多。 欲了解更多信息,请下载我们的免费 O'Reilly 电子书 -容器网络: 从 Docker 到 Kubernetes – 或者查看www.docker.com

相关文档

在 Docker 上部署 NGINX 和 NGINX Plus


“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”