介绍
Docker可以是在生产中运行Web应用程序的有效方式,但您可能希望在同一Docker主机上运行多个应用程序。 在这种情况下,您需要设置反向代理,因为您只想将端口80
和443
暴露给世界其他地方。
Traefik是一个Docker感知逆向代理,包括自己的监控仪表板。 在本教程中,您将使用Traefik将请求路由到两个不同的Web应用程序容器: Wordpress容器和一个管理员容器,每个容器都与MySQL数据库进行通信。 您将使用我们的加密配置Traefik来为HTTPS服务。
先决条件
要遵循本教程,您将需要以下信息:
一个Ubuntu 16.04服务器通过遵循Ubuntu 16.04初始服务器设置指南设置 ,包括sudo非root用户和防火墙。
一个正在运行的Docker主机。 关于如何安装和使用Ubuntu 16.04上的Docker创建一个如果您还没有。
Docker Compose安装了如何在Ubuntu 16.04上安装Docker Compose的说明 。
一个域和三个A记录,
db-admin
,blog
和monitor
,每个都指向您的Docker主机的IP地址。 您可以通过遵循如何使用DigitalOcean设置主机名来了解如何将域指向DigitalOcean Droplet。 在本教程中,将您的域替换为example.com
在配置文件和示例中。
第1步 - 配置和运行Traefik
Traefik项目具有正式的Docker映像 ,因此我们将使用它来在Docker容器中运行Traefik。
但是,在我们的Traefik容器启动并运行之前,我们需要创建一个配置文件并设置加密的密码,以便我们可以访问监控仪表板。
我们将使用htpasswd
实用程序创建此加密密码。 首先,安装apache2-utils
包中包含的实用程序:
sudo apt-get install apache2-utils`
然后用htpasswd
生成密码。 使用您要用于Traefik管理员用户的密码替换secure_password
:
htpasswd -nb admin secure_password
该程序的输出将如下所示:
Outputadmin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
您将在Traefic配置文件中使用此输出来为Traefik运行状况检查和监视仪表板设置HTTP基本身份验证。 复制整个输出行,以便稍后粘贴。
要配置Traefik服务器,我们将使用TOML格式创建一个名为traefik.toml
的新配置文件。 TOML是一种类似于INI文件的配置语言,但它是标准化的。 该文件允许我们配置我们想要使用的Traefik服务器和各种集成或提供者 。 在本教程中,我们将使用三个Traefik的可用提供程序: web
,docker和acme
,它们用于使用Let's Encrypt来支持TLS。
nano traefik.toml
首先,添加两个命名的入口点http
和https
,默认情况下所有后端都可以访问:
defaultEntryPoints = ["http", "https"]
我们稍后将在此文件中配置http
和https
入口点。
接下来,配置web
提供程序,让您访问仪表板界面。 这是您将粘贴htpasswd
命令的输出的地方:
...
[web]
address = ":8080"
[web.auth.basic]
users = ["admin:your_encrypted_password"]
仪表板是一个单独的Web应用程序,将在Traefik容器内运行。 我们设置仪表板在8080
端口上运行。
web.auth.basic
部分为仪表板配置HTTP基本身份验证。 使用刚刚运行的htpasswd
命令的输出作为users
条目的值。 您可以通过用逗号分隔来指定额外的登录。
接下来,定义入口点。 entryPoints
部分配置Traefik和代理容器可以监听的地址。 将这些行添加到文件中:
...
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
http
入口点处理端口80
,而https
入口点使用端口443
作为TLS / SSL。 我们自动将端口80
上的所有流量重定向到https
入口点,以强制所有请求的安全连接。
最后,添加本节配置让我们加密Traefik的证书支持:
...
[acme]
email = "your_email@example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false
此部分称为acme
因为ACME是用于与我们加密管理证书进行通信的协议的名称。 要让Traefik为我们的主机生成证书,我们将email
密钥设置为您的电子邮件地址。 然后我们指定我们将存储我们将从一个称为acme.json
的JSON文件中加密的信息。 entryPoint
键需要指向入口点处理端口443
,在我们的例子中是https
入口点。
最后两个关键字onHostRule
和onDemand
指示Traefik应该如何生成证书。 一旦我们创建了具有指定主机名的容器,我们就想获取证书,这就是onHostRule
设置所做的。 onDemand
设置将在首次发出请求时尝试生成证书。 这会减慢第一个请求,对访问者来说非常明显,所以我们会避免这种情况。
保存文件并退出编辑器。 随着所有这些配置到位,我们可以启动Traefik。
第2步 - 运行Traefik容器
接下来,为代理创建一个Docker网络以与容器共享。 Docker网络是必要的,因此我们可以将其与使用Docker Compose运行的应用程序一起使用。 我们来打电话给这个网络proxy
。
docker network create proxy
当Traefik容器启动时,我们将其添加到此网络。 那么我们可以在Traecik后来为此网络添加额外的容器来代理。
接下来,创建一个空文件,这将保存我们的加密信息。 我们会将它分享到容器中,因此Traefik可以使用它:
touch acme.json
然后锁定此文件的权限,以便只有root用户可以读写此文件。 如果不这样做,Traefik将无法启动。
chmod 600 acme.json
最后,使用以下命令创建Traefik容器:
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD/traefik.toml:/traefik.toml \
-v $PWD/acme.json:/acme.json \
-p 80:80 \
-p 443:443 \
-l traefik.frontend.rule=Host:monitor.example.com \
-l traefik.port=8080 \
--network proxy \
--name traefik \
traefik:1.3.6-alpine --docker
这个命令有点长,所以让我们把它弄掉。
我们使用-d
标志作为守护进程在后台运行容器。 然后,我们将docker.sock
文件共享到容器中,以便Traefik进程可以监听容器的更改。 我们还将traefik.toml
配置文件和我们创建的acme.json
文件共享到容器中。
接下来,我们将Docker主机的端口:80
和:443
映射到Traefik容器中的相同端口,以便Traefik接收到服务器的所有HTTP和HTTPS流量。
然后我们设置两个Docker标签,告诉Traefik将流量引导到主机名monitor. example.com
monitor. example.com
到端口:8080
在Traefik容器内,露出监控仪表板。
我们将容器的网络设置为proxy
,我们命名容器traefik
。
最后,我们使用traefik:1.3.6-alpine
图像作为这个容器,因为它很小。
Docker图像的ENTRYPOINT
是一个从图像创建容器时始终运行的命令。 在这种情况下,该命令是容器内的traefik
二进制文件。 启动容器时,可以向该命令传递其他参数。 在我们的例子中,我们将参数--docker
传递给ENTRYPOINT
,以确保ENTRYPOINT
提供程序注册了默认设置。 Docker提供商使Traefik能够作为Docker容器前的代理。 Docker提供程序的默认配置适用于我们,所以我们不需要在我们的traefik.toml
进行配置。
随着容器的启动,您现在可以使用一个仪表盘,您可以访问以查看容器的健康状况。 您还可以使用此仪表板来显示Traefik已注册的前端和后端。 通过将浏览器指向https://monitor. example.com
来访问监视仪表板https://monitor. example.com
https://monitor. example.com
。 系统将提示您输入用户名和密码,这些用户名和密码是您在第1步中配置的admin和密码。
登录后 你会看到一个类似于这样的界面:
目前还没有太多的看法,但是让这个窗口打开,你会看到内容改变,因为你添加容器可以使用Traefik。
我们现在让我们的Traefik代理运行,配置为与Docker一起工作,并准备监视其他Docker容器。 我们开始一些容器为Traefik作为代理。
第3步 - 向Traefik注册容器
随着Traefik容器运行,您可以随时运行应用程序。 让我们在Traefik之后推出以下的手套:
- 一个使用官方Wordpress图片的博客。
- 数据库管理服务器使用官方的Adminer映像 。
我们将使用Docker docker-compose.yml
文件对Docker Compose管理这两个应用程序:
nano docker-compose.yml
将以下行添加到文件中以指定我们将使用的版本和网络:
version: "3"
networks:
proxy:
external: true
internal:
external: false
我们使用Docker Compose版本3
因为它是Compose文件格式的最新版本。
对于Traefik来认识我们的应用程序,它们必须是同一个网络的一部分,而且由于我们手动创建了网络,所以我们通过指定proxy
的网络名称并将external
设置为true
来将其拉入。 然后我们定义另一个网络,以便我们可以将我们暴露的容器连接到我们不会通过Traefik公开的数据库容器。 我们会把这个网络称为internal
。
接下来,我们将定义每个services
,一次一个。 我们从blog
容器开始,我们将基于官方的WordPress图像。 将此配置添加到文件中:
version: "3"
...
services:
blog:
image: wordpress:4.7.5-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.backend=blog
- traefik.frontend.rule=Host:blog.example.com
- traefik.docker.network=proxy
- traefik.port=80
networks:
- internal
- proxy
depends_on:
- mysql
environment
键可以指定将在容器内设置的环境变量。 通过不为WORDPRESS_DB_PASSWORD
设置值,我们告诉Docker Compose从我们的shell获取值,并在创建容器时将其传递。 在启动容器之前,我们将在shell中定义这个环境变量。 这样我们不会将密码硬编码到配置文件中。
labels
部分是您为Traefik指定配置值的位置。 Docker标签本身不做任何事情,但Traefik读取这些标签,所以它知道如何处理容器。 以下是这些标签:
-
traefik.backend
指定traefik.backend
中的后端服务的名称(指向实际的blog
容器)。 -
traefik.frontend.rule=Host:blog. example.com
traefik.frontend.rule=Host:blog. example.com
告诉Traefik检查所请求的主机,如果它符合blog. example.com
模式blog. example.com
blog. example.com
它应该将流量路由到blog
容器。 -
traefik.docker.network=proxy
指定要查找Traefik找到该容器的内部IP的哪个网络。 由于我们的Traefik容器可以访问所有的Docker信息,所以如果没有指定这个信息,那么它可能需要internal
网络的IP。 -
traefik.port
指定Traefik应用于将流量路由到此容器的暴露端口。
使用此配置,发送到我们的Docker主机端口80
所有流量将被路由到blog
容器。
我们将此容器分配给两个不同的网络,以便Traefik可以通过proxy
网络找到它,并且可以通过internal
网络与数据库容器进行通信。
最后, depends_on
键告诉Docker Compose,这个容器在依赖关系运行后需要启动。 由于WordPress需要一个数据库才能运行,所以我们必须在启动我们的blog
容器之前运行我们的mysql
容器。
接下来,通过将此配置添加到您的文件来配置MySQL服务:
services:
...
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
我们正在使用这个容器的官方MySQL 5.7映像。 你会注意到,我们再次使用没有价值的environment
项目。 MYSQL_ROOT_PASSWORD
和WORDPRESS_DB_PASSWORD
变量将需要设置为相同的值,以确保我们的WordPress容器可以与MySQL进行通信。 我们不想将mysql
容器暴露给Traefik或外部世界,所以我们只将这个容器分配给internal
网络。 由于Traefik可以访问Docker套接字,所以默认情况下,该进程仍然会暴露出mysql
容器的前端,因此我们将添加标签traefik.enable=false
以指定Traefik不应该暴露此容器。
最后,添加此配置来定义Adminer容器:
services:
...
adminer:
image: adminer:4.3.1-standalone
labels:
- traefik.backend=adminer
- traefik.frontend.rule=Host:db-admin.example.com
- traefik.docker.network=proxy
- traefik.port=8080
networks:
- internal
- proxy
depends_on:
- mysql
这个容器是基于官方的Adminer图像。 该容器的network
和depends_on
配置与我们用于blog
容器的配置完全匹配。
但是,由于我们将Docker主机上的端口80
所有流量直接引导到blog
容器,所以我们需要以不同的方式配置此容器,以便流量使其成为adminer
容器。 行traefik.frontend.rule=Host:db-admin. example.com
traefik.frontend.rule=Host:db-admin. example.com
告诉Traefik来检查所请求的主机。 如果它匹配db-admin. example.com
的模式db-admin. example.com
db-admin. example.com
Traefik会将流量路由到adminer
容器。
保存文件并退出文本编辑器。
接下来,在启动容器之前,为您的shell设置WORDPRESS_DB_PASSWORD
和MYSQL_ROOT_PASSWORD
变量的值:
export WORDPRESS_DB_PASSWORD=secure_database_password
export MYSQL_ROOT_PASSWORD=secure_database_password
用您所需的数据库密码替换secure_database_password
。
使用这些变量设置,使用docker-compose
运行容器:
docker-compose up -d
现在再来看一下Traefik管理仪表板。 您会看到现在有两个外部服务器的backend
和frontend
:
浏览blog. example.com
blog. example.com
,用你的域名替换example.com
。 您将被重定向到TLS连接,现在可以完成Wordpress设置:
现在通过访问db-admin. example.com
访问Adminer db-admin. example.com
db-admin. example.com
在您的浏览器中,再次用您的域名example.com
。 mysql
容器不会暴露给外界,但是adminer
容器可以通过使用mysql
容器名称作为主机名共享的internal
Docker网络来访问它。
在管理员登录屏幕上,使用用户名root ,使用mysql
作为服务器 ,并使用为MYSQL_ROOT_PASSWORD
设置的值作为密码。 登录后,您将看到Adminer用户界面:
这两个网站现在都在工作,您可以在monitor. example.com
使用仪表板monitor. example.com
monitor. example.com
来关注您的应用程序。
结论
在本教程中,您已将Traefik配置为向Docker容器中的其他应用程序提供代理请求。
Traefik在应用程序容器级别的声明式配置可以轻松配置更多服务,并且当您将新应用程序添加到代理流量时,不需要重新启动traefik
容器,因为Traefik会立即通过其监视的Docker套接字文件来注意到这些更改。
要了解有关Traefik可以做什么的更多信息,请转到官方的Traefik文档 。