在处理 Web 应用程序服务器的请求和提供静态内容时,长期以来经受考验的 Nginx 如今是一个极其受欢迎的选择。当您使用 Docker 并将应用程序容器化时,让 Nginx 同样为其提供服务在大多数情况下是有意义的。毕竟,这些容器使您能够轻松移植应用程序,快速扩展,并为您的主机(即 droplets)的安全性增加另一层。
在这篇 DigitalOcean 文章中,我们将学习如何快速设置 Docker,从基础镜像创建 Docker 容器,并逐层构建以运行 Nginx。随后,按照我们从头开始的步骤,我们将创建一个 Dockerfile 来自动化整个过程。最后,使用这个 Nginx Docker 镜像,您将能够创建运行 Nginx 的自包含沙盒,用于提供您的“docker化”应用程序。
Docker 项目提供了一些在一些 Linux 内核特性之上构建的高级工具,这些工具共同工作,旨在帮助开发人员和系统管理员将应用程序及其所有依赖项一起移植,并在系统和机器上运行,无需烦恼。
Docker 通过创建安全的、基于 LXC(即 Linux 容器)的应用程序环境,称为“Docker 容器”,来实现这一目标。这些容器是使用 Docker 镜像创建的,可以通过手动执行命令或通过 Dockerfile 自动构建。
注意: 要了解更多关于 Docker 及其组成部分(例如 Docker 守护进程、CLI、镜像等)的信息,请查看我们的项目介绍文章:Docker 解释:入门指南。
Nginx 是一个非常高性能的 Web 服务器 / (反向)代理。它因其轻量级、相对易于使用和易于扩展(具有插件/附加组件)而广受欢迎。由于其架构,它能够处理大量的请求(几乎无限),这取决于您的应用程序或网站负载,使用旧的替代方案可能会非常困难。它可以被认为是选择用于提供静态文件(如图像、脚本或样式表)的工具。
在其最新版本(0.7.1. 于 12 月 5 日发布)中,Docker 可以部署在包括 Ubuntu / Debian 和 CentOS / RHEL 在内的各种 Linux 操作系统上。
请记住,您可以通过使用 DigitalOcean 基于 Ubuntu 13.04 构建的即用即用的 Docker 镜像快速入门。
我们将快速浏览 Ubuntu(最新版)的安装过程。
更新您的 droplet:
sudo aptitude update sudo aptitude -y upgrade
确保可用 aufs 支持:
sudo aptitude install linux-image-extra-`uname -r`
将 Docker 存储库密钥添加到 apt-key 以进行软件包验证:
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
将 Docker 存储库添加到 aptitude 源:
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\ > /etc/apt/sources.list.d/docker.list"
使用新添加的内容更新存储库:
sudo aptitude update
最后,下载并安装 Docker:
sudo aptitude install lxc-docker
Ubuntu 的默认防火墙(UFW:简化防火墙)默认拒绝所有转发流量,这是 Docker 需要的。
使用 UFW 启用转发:
使用 nano 文本编辑器编辑 UFW 配置。
sudo nano /etc/default/ufw
向下滚动并找到以 DEFAULT_FORWARD_POLICY 开头的行。
将:
DEFAULT_FORWARD_POLICY="DROP"
替换为:
DEFAULT_FORWARD_POLICY="ACCEPT"
按下 CTRL+X 并批准使用 Y 保存并关闭。
最后,重新加载 UFW:
sudo ufw reload
在我们开始使用 Docker 之前,让我们快速回顾一下可用的命令,以便从我们的第一篇**入门**文章中刷新我们的记忆。
安装完成后,Docker 守护进程应该在后台运行,准备接受 Docker CLI 发送的命令。在某些情况下,可能需要手动运行 Docker,使用以下命令:
运行 Docker 守护进程:
sudo docker -d &
Docker CLI 使用:
sudo docker [option] [command] [arguments]
注意: Docker 需要 sudo 权限才能运行。
以下是当前可用的(版本0.7.1)Docker 命令的摘要:
attach: 附加到正在运行的容器 build: 从 Dockerfile 构建容器 commit: 从容器的更改创建新镜像 cp: 从容器文件系统复制文件/文件夹到主机路径 diff: 检查容器文件系统的更改 events: 从服务器获取实时事件 export: 将容器内容作为 tar 存档流式传输 history: 显示镜像的历史记录 images: 列出镜像 import: 从 tar 存档的内容创建新文件系统镜像 info: 显示系统范围的信息 insert: 在镜像中插入文件 inspect: 返回容器的低级信息 kill: 终止正在运行的容器 load: 从 tar 存档加载镜像 login: 注册或登录到 Docker 注册服务器 logs: 获取容器的日志 port: 查找映射到 PRIVATE_PORT 的公共端口 ps: 列出容器 pull: 从 Docker 注册服务器拉取镜像或存储库 push: 将镜像或存储库推送到 Docker 注册服务器 restart: 重新启动正在运行的容器 rm: 删除一个或多个容器 rmi: 删除一个或多个镜像 run: 在新容器中运行命令 save: 将镜像保存为 tar 存档 search: 在 Docker 索引中搜索镜像 start: 启动已停止的容器 stop: 停止正在运行的容器 tag: 将镜像标记为存储库 top: 查找容器的运行进程 version: 显示 Docker 版本信息
===
在我们的 VPS 上安装了 Docker 并快速浏览了其命令之后,我们准备开始实际工作,创建运行 Nginx 的 Docker 容器。
注意: 尽管在遵循本节后,我们将拥有一个安装了 Nginx 的运行中的 Docker 容器,但由于其复杂性,这绝对不是推荐的方法。然而,这里提供给您一个机会,让您学习如何使用一个活动容器,并熟悉我们稍后需要定义的命令,以自动化该过程。要以更好的方式创建安装了 Nginx 的 Docker 镜像,请参阅下一节:创建 Dockerfile 自动构建 Nginx 镜像。
使用 Docker 的 RUN 命令,我们将从基于 Ubuntu 镜像创建一个新的容器。我们将使用“-t”标志附加一个终端到它上面。
sudo docker run -i -t -p 80:80 ubuntu /bin/bash
注意: 执行此命令后,Docker 可能需要在为您创建新容器之前拉取Ubuntu 镜像。
记住: 您将附加到您创建的容器上。为了分离自己并返回到主终端访问点,请运行转义序列:CTRL+P,然后是CTRL+Q。附加到 Docker 容器就像从另一个内部连接到一个新的 droplet。
要重新附加到此容器:
重要: 请不要忘记,由于我们在一个容器中,所有后续命令将在其中执行,而不会影响主机。
为了安装 Nginx 和我们将需要的工具,相关的应用程序存储库必须可供下载。
让我们将 Ubuntu 的universe追加到基本镜像的默认列表中。
echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
使用新添加的源更新列表。
apt-get update
在我们继续安装 Nginx之前,有一些工具我们应该安装,比如 nano - 以防万一。
apt-get install -y nano \ wget \ dialog \ net-tools
由于 Nginx 可以在软件仓库中找到,我们可以简单地使用 apt-get 来下载并安装 Nginx。
apt-get install -y nginx
使用我们在上一步中安装的文本编辑器 nano,让我们创建一个简单的 Nginx 配置来代理连接到应用服务器。
# 删除默认配置 rm -v /etc/nginx/nginx.conf # 使用 nano 文本编辑器创建一个空白配置文件 nano /etc/nginx/nginx.conf
首先,在文件顶部,必须添加一行来禁止 Nginx 生成其进程然后退出。
我们不能允许这种情况发生的原因是因为 Docker 依赖于单个进程运行(甚至可以是进程管理器),当该进程停止(即在生成工作进程后退出),容器也会停止。
在 nginx.conf 的第一行添加以下内容:
daemon off;
我们将使用一个简单的样本配置来让 Nginx 作为反向代理运行。在 daemon off; 指令之后,复制并粘贴以下内容。
worker_processes 1; events { worker_connections 1024; } http { sendfile on; gzip on; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 500; gzip_disable "MSIE [1-6]\."; gzip_types text/plain text/xml text/css text/comma-separated-values text/javascript application/x-javascript application/atom+xml; # 应用服务器列表 upstream app_servers { server 127.0.0.1:8080; } # 服务器配置 server { # 运行端口 listen 80; # 代理连接 location / { proxy_pass http://app_servers; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } }
保存并退出,按下 CTRL+X,然后确认选择 Y。
要运行 Nginx,可以执行以下命令:
service nginx start
就是这样!我们现在在一个 Docker 容器中运行着 Nginx,可以通过端口 80 从外部访问,就像我们使用 -p 80:80 标志设置的那样。
记住: 尽管这个 Nginx 文件已经正确配置,但由于当前服务器上没有运行应用服务器,它不会起作用。在安装和运行应用服务器之前,你可以复制并使用另一个示例,它只是作为一个转发代理来测试 HTTP 标头。
正如我们在上一步中提到的,这绝对不是可扩展生产环境中创建容器的推荐方式。正确的做法可以被认为是使用 Dockerfile 来自动化构建过程,以结构化的方式。
在完成了在容器中下载和安装 Nginx的必要命令之后,我们可以使用相同的知识来编写一个 Dockerfile,Docker 可以使用它来构建一个镜像,然后可以轻松地运行 Nginx 实例。
在我们开始编写 Dockerfile 之前,让我们快速了解一下基础知识。
Dockerfile 是包含连续声明的命令的脚本,这些命令将按顺序由 Docker 执行,以自动创建一个新的 Docker 镜像。它们在部署中非常有帮助。
这些文件始终以使用 FROM 命令定义基础镜像开始。从那里开始,构建过程 开始,接下来的每个操作都形成最终的镜像,该镜像将被提交到主机上。
用法:
# 使用当前位置的 Dockerfile 构建一个镜像 # 使用 [name] 标记最终镜像(例如 *nginx*) # 示例:sudo docker build -t [name] . sudo docker build -t nginx_img .
注意: 要了解更多关于 Dockerfile 的信息,请查看我们的文章:Docker 解释:使用 Dockerfile 自动构建镜像。
要使用 nano 文本编辑器在当前位置创建 Dockerfile,请执行以下命令:
sudo nano Dockerfile
注意: 请依次添加以下所有行,以形成要保存和用于构建的 Dockerfile。
让我们从定义基本内容(基础知识)开始编写 Dockerfile,例如 FROM 镜像(即 Ubuntu)和 MAINTAINER。
############################################################ # 用于构建安装了 Nginx 的容器的 Dockerfile # 基于 Ubuntu ############################################################ # 将基础镜像设置为 Ubuntu FROM ubuntu # 文件作者 / 维护者 MAINTAINER 维护者姓名
按照上一节的步骤,让我们形成一个块来安装 Nginx。
# 安装 Nginx # 将应用程序仓库 URL 添加到默认源中 RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list # 更新仓库 RUN apt-get update # 安装必要工具 RUN apt-get install -y nano wget dialog net-tools # 下载并安装 Nginx RUN apt-get install -y nginx
在添加安装 Nginx 的指令后,让我们完成配置 Nginx,并让 Dockerfile 在构建过程中用我们提供的配置文件替换默认配置文件。
# 删除默认的 Nginx 配置文件 RUN rm -v /etc/nginx/nginx.conf # 从当前目录复制一个配置文件 ADD nginx.conf /etc/nginx/ # 在配置文件开头添加 "daemon off;" RUN echo "daemon off;" >> /etc/nginx/nginx.conf # 暴露端口 EXPOSE 80 # 设置创建新容器时要执行的默认命令 CMD service nginx start
最终,Dockerfile 应该如下所示:
############################################################ # 用于构建安装了 Nginx 的容器的 Dockerfile # 基于 Ubuntu ############################################################ # 将基础镜像设置为 Ubuntu FROM ubuntu # 文件作者 / 维护者 MAINTAINER 维护者姓名 # 安装 Nginx # 将应用程序仓库 URL 添加到默认源中 RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list # 更新仓库 RUN apt-get update # 安装必要工具 RUN apt-get install -y nano wget dialog net-tools # 下载并安装 Nginx RUN apt-get install -y nginx # 删除默认的 Nginx 配置文件 RUN rm -v /etc/nginx/nginx.conf # 从当前目录复制一个配置文件 ADD nginx.conf /etc/nginx/ # 在配置文件开头添加 "daemon off;" RUN echo "daemon off;" >> /etc/nginx/nginx.conf # 暴露端口 EXPOSE 80 # 设置创建新容器时要执行的默认命令 CMD service nginx start
再次按下 CTRL+X 保存并退出文件。
正如我们在“基础知识”部分中首次介绍的那样,Dockerfile 的使用包括使用 “docker build” 命令调用它们。
由于我们指示 Docker 复制一个配置文件(即 nginx.conf)从当前目录替换默认配置文件,因此在开始构建过程之前,我们需要确保它与此 Dockerfile 同在一个目录中。
注意: 上述解释的复制 进 Nginx 配置的过程使您具有很大的灵活性,并通过不必处理附加和分离自己从容器中创建配置文件来节省了大量时间。现在,您可以简单地使用一个命令直接构建和运行镜像。
使用文本编辑器 nano 创建一个示例 nginx.conf:
sudo nano nginx.conf
并替换其内容以将其用作用于测试的转发代理:
worker_processes 1; events { worker_connections 1024; } http { sendfile on; server { listen 80; location / { proxy_pass http://httpstat.us/; proxy_set_header X-Real-IP $remote_addr; } } }
同样按下 CTRL+X 保存并退出 nginx.conf。
这个 Docker 镜像将允许我们将所有进度移植,并快速创建运行 Nginx 的容器。
要开始使用它,请使用以下命令构建一个新的容器镜像:
sudo docker build -t nginx_img_1 .
然后使用我们标记为 nginx_img_1 的镜像 - 我们可以运行一个新的容器:
sudo docker run -name nginx_cont_1 -p 80:80 -i -t nginx_img_1
现在您可以访问您的 droplet 的 IP 地址,您的 Nginx 运行的 Docker 容器将执行其工作,将您转发到 HTTP 状态测试页面。
示例:
# 用法:访问 http://[我的 droplet 的 IP] http://95.85.10.236/200
示例响应:
200 OK