Docker是在生产中运行Web应用程序的有效方法,但您可能希望在同一个Docker主机上运行多个应用程序。在这种情况下,如果只有端口80
和443
可用,您需要设置反向代理。
Traefik是一个支持Docker的反向代理,包括自己的监控仪表板。在本教程中,您将使用Traefik请求路由到两个不同的Web应用程序容器:Wordpress容器和Adminer容器,每个容器都与MySQL数据库通信。
要继续学习本教程,您需要具备以下条件:
db-admin
,blog
和monitor
,每个对应docker主机的IP地址。Traefik项目有一个官方Docker镜像,因此我们将使用它在Docker容器中运行Traefik。
但在我们启动并运行Traefik容器之前,我们需要创建配置文件并设置加密密码,以便我们可以访问监控仪表板。
我们将使用htpasswd
实用程序创建此加密密码。首先,安装apache2-utils
包中包含的实用程序:
$ sudo apt-get install apache2-utils
然后生成密码htpasswd
。用secure_password
替换您想要用于Traefik管理员用户的密码:
$ htpasswd -nb admin secure_password
程序的输出如下所示:
admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
您将在Traefic配置文件中使用此输出为Traefik运行状况检查和监视仪表板设置HTTP基本身份验证。复制整个输出行,以便稍后粘贴。
要配置Traefik服务器,我们将创建一个使用TOML格式调用的新配置文件traefik.toml
。TOML是一种类似于INI文件的配置语言,但它是标准化的。该文件允许我们配置Traefik服务器以及我们想要使用的各种集成或提供程序。在本教程中,我们将使用三个Traefik的可用提供商:web
,docker
,和acme
,这是用于支持TLS加密。
$ nano traefik.toml
首先,添加两个命名的入口点,http
和https
,默认情况下所有后端都可以访问:
traefik.toml
defaultEntryPoints = ["http", "https"]
我们稍后将在此文件中配置http
和https
。
接下来,配置web
提供程序,使您可以访问仪表板界面。您可以在此处粘贴htpasswd
命令的输出:
traefik.toml
...
[web]
address = ":8080"
[web.auth.basic]
users = ["admin:your_encrypted_password"]
仪表板是一个单独的Web应用程序,将在Traefik容器中运行。我们将仪表板设置为在端口8080上运行。
该web.auth.basic
部分为仪表板配置HTTP基本身份验证。使用您刚刚运行的htpasswd
命令的输出作为users
条目的值。您可以通过用逗号分隔来指定其他登录。
接下来,定义入口点。该entryPoints
部分配置Traefik和代理容器可以侦听的地址。将这些行添加到文件中:
traefik.toml
...
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
该http
入口点处理端口80
,而https
入口点为TLS /SSL使用的端口443
。我们自动将端口80
上的所有流量重定向到https
入口点,以强制所有请求的安全连接。
最后,添加此部分以配置Traefik的Let's Encrypt证书支持:
traefik.toml
...
[acme]
email = "your_email@example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false
调用此acme部分是因为ACME是用于与Let’s Encrypt进行通信以管理证书的协议的名称。要让Traefik为我们的主机生成证书,我们会将email密钥设置为您的电子邮件地址。然后,我们指定将把接收的信息存储在JSON文件中,命名为acme.json
。在entryPoint关键的需求为指向切入点端口443,这对我们来说是https切入点。
最后两个关键步骤,onHostRule
和onDemand
指示Traefik应该如何生成证书。我们希望在创建具有指定主机名的容器后立即获取证书,这就是onHostRule设置的作用。该onDemand设置将尝试在第一次发出请求时生成证书。这会减慢第一个请求速度并使访问者可见,所以我们会避免这种情况。
保存文件并退出编辑器。有了所有这些配置,我们就可以启动Traefik了。
接下来,为代理创建一个Docker网络以与容器共享。Docker网络是必需的,以便我们可以将它与使用Docker Compose运行的应用程序一起使用。我们把这个网络称为proxy
。
$ docker network create proxy
当Traefik容器启动时,我们会将其添加到此网络中。然后,我们可以稍后向此网络添加其他容器,以便Traefik代理。
接下来,创建一个空文件,它将保存我们的信息。我们将这个分享到容器中,以便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文件共享到容器中。
接下来,我们将端口:80
和:443
Docker主机映射到Traefik容器中的相同端口,以便Traefik接收到服务器的所有HTTP和HTTPS流量。
然后我们设置两个Docker标签,告诉Traefik将流量引导到Traefik容器内的主机名monitor.example.com
到端口:8080
,从而显示监控仪表板。我们将容器的网络设置为proxy
,并将容器命名为traefik。
最后,我们使用此容器的镜像traefik:1.3.6-alpine
,因为它很小。
Docker镜像ENTRYPOINT
是一个始终在从图像创建容器时运行的命令。在这种情况下,该命令是traefik容器内的二进制文件。启动容器时,可以将其他参数传递给该命令。在我们的例子中,我们将参数--docker传递给ENTRYPOINT确保docker提供者使用默认设置注册的参数。该docker提供程序使Traefik能够在Docker容器前充当代理。Docker提供程序的默认配置对我们很有用,因此我们不需要在我们的配置traefik.toml中进行配置。
启动容器后,您现在可以访问仪表板以查看容器的运行状况。您还可以使用此仪表板显示Traefik已注册的前端和后端。通过指向您的浏览器访问监控仪表板。系统将提示您输入用户名和密码,即管理员和您在步骤1中配置的密码。https://monitor.example.com
登录后,你会看到类似这样的界面:
目前还没有太多东西可以看,但是打开这个窗口,当你为Traefik添加容器时,你会看到内容发生了变化。
我们现在运行Traefik代理,配置为与Docker一起使用,并准备监视其他Docker容器。让我们为Traefik开始一些容器作为代理。
运行Traefik容器后,您就可以在其后面运行应用程序了。让我们在Traefik后面推出以下cotainers:
我们将使用Docker Compose管理这两个docker-compose.yml
文件应用程序:
$ nano docker-compose.yml
将以下行添加到文件中以指定我们将使用的版本和网络:
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镜像。将此配置添加到文件中:
docker-compose.yml
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中后端服务的名称(指向实际blog容器)。traefik.frontend.rule=Host:blog.example.com
告诉Traefik检查所请求的主机,如果它匹配它的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需要运行数据库,因此我们必须在启动容器mysql之前运行我们的blog容器。
接下来,通过将此配置添加到您的文件来配置MySQL服务:
docker-compose.yml
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 socket,因此默认情况下该进程仍会暴露容器mysql的前端,因此我们将添加标签traefik.enable=false
以指定Traefik不应公开此容器。
最后,添加此配置以定义Admine
r容器:
docker-compose.yml
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检查所请求的主机。如果匹配Traefik 的模式将流量db-admin.example.com
路由到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
并替换您的域名example.com
。您将被重定向到TLS连接,现在可以完成Wordpress设置:
现在用Adminer浏览器访问db-admin.example.com
,再次使用您的域名example.com
替换。该mysql容器未显示在外界,但adminer容器仍可以通过internal
docker访问它。
在Adminer登录屏幕上,使用用户名root,mysql用于服务器,并使用您为密码设置的MYSQL_ROOT_PASSWORD
值。登录后,您将看到Adminer用户界面:
这两个站点现在都在monitor.example.com
工作,您可以使用仪表板来监视您的应用程序。
在本教程中,您将Traefik配置为将请求代理到Docker容器中的其他应用程序。
Traefik在应用程序容器级别的声明性配置使得配置更多服务变得容易,并且在traefik向代理流量添加新应用程序时无需重新启动容器,因为Traefik会通过它正在监视的Docker socket文件立即进行更改。
参考文献:《How to Use Traefik as a Reverse Proxy for Docker Containers on Ubuntu 16.04》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。