如何将 Traefik 服务添加到现有 Docker Swarm 集群?
How to add a Traefik service to an existing Docker Swarm cluster?
我有一个 Web 应用程序,我可以使用 Docker Swarm 和 Compose 文件成功部署:
docker stack deploy --compose-file docker-compose.yml common
并由文件描述:
version: "3.8"
services:
www:
image: localhost:5000/www.learnintouch
ports:
- "81:80"
- "444:443"
networks:
common:
networks:
common:
name: common
现在我给它添加一个Traefik服务:
version: "3.8"
services:
traefik:
image: traefik
ports:
- target: 81
published: 80
mode: host
- target: 8080
published: 8080
mode: host
- target: 444
published: 443
mode: host
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.docker.network=common
- traefik.constraint-label=common
- traefik.docker.lbswarm=true
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
- "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
www:
image: localhost:5000/www.learnintouch
ports:
- "81:80"
- "444:443"
labels:
- "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
networks:
common:
networks:
common:
name: common
default:
driver: overlay
容器已部署:
22:49 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff38498c061f localhost:5000/www.learnintouch:latest "/bin/bash /usr/loca…" About a minute ago Up About a minute (healthy) www_learnintouch_www.1.n9mvfo64hp8unzvcau6rws99q
df070019539f traefik:latest "/entrypoint.sh --lo…" 2 minutes ago Up 2 minutes 80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:80->81/tcp, :::80->81/tcp, 0.0.0.0:443->444/tcp, :::443->444/tcp common_traefik.1.t141a053tvcbi0ql5ztbjmfgp
但是端口映射存在一些问题:
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:52:24Z" level=error msg="service \"common-traefik\" error: port is missing" providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:52:39Z" level=error msg="service \"www-learnintouch-www\" error: port is missing" providerName=docker container=www-learnintouch-www-n9mvfo64hp8unzvcau6rws99q
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:53:24Z" level=warning msg="Could not find network named 'common' for container 'common_traefik'! Maybe you're missing the project's prefix in the label? Defaulting to first available network." providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9 serviceName=common-traefik
我没有使用其他命令手动创建网络,因为在添加 Traefik
服务之前我不需要这样做。
作为 Traefik
和网络虚拟机,我希望安装简单,而不必手动冗余指定主机名,也不必 运行 一些外部命令。
在搜索提示后,我找到了这个 opened issue 但我不知道该怎么做。
更新:我为所有服务添加了一个端口,如下所示:
labels:
- "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
- "traefik.http.services.www.loadbalancer.server.port=5000"
但日志仍然显示相同的错误消息。
更新:提供解决方案后的文件:
version: "3.9"
services:
traefik:
image: traefik
networks:
common:
ports:
- target: 81
published: 80
mode: host
- target: 444
published: 443
mode: host
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
- "traefik.constraint-label=common"
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
--providers.docker.network=common
--providers.docker.exposedbydefault=false
--providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
- "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
logrotate:
image: localhost:5000/logrotate
networks:
common:
labels:
- "traefik.enable=false"
volumes:
- "~/dev/docker/projects/common/volumes/logs:/usr/local/logrotate/logs"
user: "${CURRENT_UID}:${CURRENT_GID}"
environment:
HOST_USER_ID: ${CURRENT_UID}
HOST_GROUP_ID: ${CURRENT_GID}
www:
image: localhost:5000/www.learnintouch
labels:
- "traefik.enable=true"
- "traefik.http.services.www.loadbalancer.server.port=80"
networks:
common:
volumes:
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/data:/usr/local/learnintouch/www/learnintouch.com/account/data"
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/backup:/usr/local/learnintouch/www/learnintouch.com/account/backup"
- "~/dev/docker/projects/learnintouch/volumes/engine:/usr/local/learnintouch/engine"
- "~/dev/docker/projects/common/volumes/letsencrypt/certbot/conf/live/thalasoft.com:/usr/local/learnintouch/letsencrypt"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/apache/logs"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"
user: "${CURRENT_UID}:${CURRENT_GID}"
environment:
HOST_USER_ID: ${CURRENT_UID}
HOST_GROUP_ID: ${CURRENT_GID}
DB_HOST: mysql
DB_PORT: 3306
WWW_LEARNINTOUCH_DB_NAME: db_learnintouch
WWW_LEARNINTOUCH_DB_USER: learnintouch
WWW_LEARNINTOUCH_NAME: learnintouch
WWW_LEARNINTOUCH_DOMAIN: dev.learnintouch.com
WWW_LEARNINTOUCH_SCHEME: http
STAFF_EMAIL: mittiprovence@yahoo.se
NODEJS_SOCKET_PORT: 9001
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 10s
healthcheck:
test: curl --fail http://127.0.0.1:80/engine/ping.php || exit 1
interval: 10s
timeout: 10s
retries: 3
networks:
common:
name: common
default:
driver: overlay
在 docker swarm 模式下 traefik 无法(出于某种原因!?)检测服务正在侦听的端口。
因此,每个 docker 服务都需要具有以下形式的标签:
"traefik.http.services.www_learnintouch.loadbalancer.server.port=8080"
--
我在第一遍中错过了 www
服务。
您需要从 www
中删除 ports
部分,因为 traefik 需要处理入口,并成为实际公开这些端口的服务。
然后,你还需要添加 networks: [ common ]
到 traefik,因为它不能在不共享公共网络的情况下进行路由。
最后,traefik 默认公开所有服务,因此将为您的 swarm 上未配置 full/minimal 组 traefik 标签(包括其自身)的任何和所有服务发出错误。出于某种原因,维护人员对这种愚蠢且应该修复的想法充耳不闻。
如果我们解决了这些问题,我建议使用如下所示的 traefik 服务:
version: "3.9"
services:
traefik:
image: traefik
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
networks:
- common
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.services.traefik.loadbalancer.server.port=8080
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
--providers.docker.network=common
--providers.docker.exposedbydefault=false
--providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
您的 www
服务将是:
www_learnintouch:
image: localhost:5000/www.learnintouch
labels:
- traefik.enable=true
- traefik.http.services.www_learnintouch.loadbalancer.server.port=80
networks:
common:
我有一个 Web 应用程序,我可以使用 Docker Swarm 和 Compose 文件成功部署:
docker stack deploy --compose-file docker-compose.yml common
并由文件描述:
version: "3.8"
services:
www:
image: localhost:5000/www.learnintouch
ports:
- "81:80"
- "444:443"
networks:
common:
networks:
common:
name: common
现在我给它添加一个Traefik服务:
version: "3.8"
services:
traefik:
image: traefik
ports:
- target: 81
published: 80
mode: host
- target: 8080
published: 8080
mode: host
- target: 444
published: 443
mode: host
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.docker.network=common
- traefik.constraint-label=common
- traefik.docker.lbswarm=true
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
- "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
www:
image: localhost:5000/www.learnintouch
ports:
- "81:80"
- "444:443"
labels:
- "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
networks:
common:
networks:
common:
name: common
default:
driver: overlay
容器已部署:
22:49 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff38498c061f localhost:5000/www.learnintouch:latest "/bin/bash /usr/loca…" About a minute ago Up About a minute (healthy) www_learnintouch_www.1.n9mvfo64hp8unzvcau6rws99q
df070019539f traefik:latest "/entrypoint.sh --lo…" 2 minutes ago Up 2 minutes 80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:80->81/tcp, :::80->81/tcp, 0.0.0.0:443->444/tcp, :::443->444/tcp common_traefik.1.t141a053tvcbi0ql5ztbjmfgp
但是端口映射存在一些问题:
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:52:24Z" level=error msg="service \"common-traefik\" error: port is missing" providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:52:39Z" level=error msg="service \"www-learnintouch-www\" error: port is missing" providerName=docker container=www-learnintouch-www-n9mvfo64hp8unzvcau6rws99q
common_traefik.1.t141a053tvcb@stephane-pc | time="2021-06-13T20:53:24Z" level=warning msg="Could not find network named 'common' for container 'common_traefik'! Maybe you're missing the project's prefix in the label? Defaulting to first available network." providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9 serviceName=common-traefik
我没有使用其他命令手动创建网络,因为在添加 Traefik
服务之前我不需要这样做。
作为 Traefik
和网络虚拟机,我希望安装简单,而不必手动冗余指定主机名,也不必 运行 一些外部命令。
在搜索提示后,我找到了这个 opened issue 但我不知道该怎么做。
更新:我为所有服务添加了一个端口,如下所示:
labels:
- "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
- "traefik.http.services.www.loadbalancer.server.port=5000"
但日志仍然显示相同的错误消息。
更新:提供解决方案后的文件:
version: "3.9"
services:
traefik:
image: traefik
networks:
common:
ports:
- target: 81
published: 80
mode: host
- target: 444
published: 443
mode: host
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
- "traefik.constraint-label=common"
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
--providers.docker.network=common
--providers.docker.exposedbydefault=false
--providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
- "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
logrotate:
image: localhost:5000/logrotate
networks:
common:
labels:
- "traefik.enable=false"
volumes:
- "~/dev/docker/projects/common/volumes/logs:/usr/local/logrotate/logs"
user: "${CURRENT_UID}:${CURRENT_GID}"
environment:
HOST_USER_ID: ${CURRENT_UID}
HOST_GROUP_ID: ${CURRENT_GID}
www:
image: localhost:5000/www.learnintouch
labels:
- "traefik.enable=true"
- "traefik.http.services.www.loadbalancer.server.port=80"
networks:
common:
volumes:
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/data:/usr/local/learnintouch/www/learnintouch.com/account/data"
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/backup:/usr/local/learnintouch/www/learnintouch.com/account/backup"
- "~/dev/docker/projects/learnintouch/volumes/engine:/usr/local/learnintouch/engine"
- "~/dev/docker/projects/common/volumes/letsencrypt/certbot/conf/live/thalasoft.com:/usr/local/learnintouch/letsencrypt"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/apache/logs"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"
user: "${CURRENT_UID}:${CURRENT_GID}"
environment:
HOST_USER_ID: ${CURRENT_UID}
HOST_GROUP_ID: ${CURRENT_GID}
DB_HOST: mysql
DB_PORT: 3306
WWW_LEARNINTOUCH_DB_NAME: db_learnintouch
WWW_LEARNINTOUCH_DB_USER: learnintouch
WWW_LEARNINTOUCH_NAME: learnintouch
WWW_LEARNINTOUCH_DOMAIN: dev.learnintouch.com
WWW_LEARNINTOUCH_SCHEME: http
STAFF_EMAIL: mittiprovence@yahoo.se
NODEJS_SOCKET_PORT: 9001
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 10s
healthcheck:
test: curl --fail http://127.0.0.1:80/engine/ping.php || exit 1
interval: 10s
timeout: 10s
retries: 3
networks:
common:
name: common
default:
driver: overlay
在 docker swarm 模式下 traefik 无法(出于某种原因!?)检测服务正在侦听的端口。
因此,每个 docker 服务都需要具有以下形式的标签:
"traefik.http.services.www_learnintouch.loadbalancer.server.port=8080"
--
我在第一遍中错过了 www
服务。
您需要从 www
中删除 ports
部分,因为 traefik 需要处理入口,并成为实际公开这些端口的服务。
然后,你还需要添加 networks: [ common ]
到 traefik,因为它不能在不共享公共网络的情况下进行路由。
最后,traefik 默认公开所有服务,因此将为您的 swarm 上未配置 full/minimal 组 traefik 标签(包括其自身)的任何和所有服务发出错误。出于某种原因,维护人员对这种愚蠢且应该修复的想法充耳不闻。
如果我们解决了这些问题,我建议使用如下所示的 traefik 服务:
version: "3.9"
services:
traefik:
image: traefik
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
networks:
- common
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.services.traefik.loadbalancer.server.port=8080
command:
--log.level=DEBUG
--api.insecure=true
--providers.docker
--providers.docker.swarmmode
--accesslog
--api.dashboard=true
--providers.docker.network=common
--providers.docker.exposedbydefault=false
--providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
您的 www
服务将是:
www_learnintouch:
image: localhost:5000/www.learnintouch
labels:
- traefik.enable=true
- traefik.http.services.www_learnintouch.loadbalancer.server.port=80
networks:
common: