# Converting traefik from docker to one that enables reverse proxy to docker swarm

**URL:** <https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705>\
**Category:** Traefik v3 (latest)\
**Tags:** docker-swarm\
**Created:** [March 1, 2025, 3:07am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705 "2025-03-01T03:07:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 1, 2025, 3:07am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/1 "2025-03-01T03:07:46Z")

</div>

Newbie alert.  
I have managed , with lots of help from Techno Tim (Youtube) and Jim's Garage (Youtube) to setup traefik for docker containers for a single proxmox VM. I read that to enable reverse proxy to other nodes, I should setup a docker swarm , which I also setup for 5 nodes

I do not know where to start on editing my docker-compose, and traefik.yml even after reading quite a big as its quite confusing.  
Hopefully, some kind forumers can help me.  
docker-compose.yaml  
services:  
traefik:  
image: traefik:latest  
container\_name: traefik  
restart: unless-stopped  
security\_opt:  
- no-new-privileges:true  
networks:  
- proxy  
ports:  
- 80:80  
- 443:443  
# - 443:443/tcp # Uncomment if you want HTTP3  
# - 443:443/udp # Uncomment if you want HTTP3  
environment:  
CF\_DNS\_API\_TOKEN\_FILE: /run/secrets/cf\_api\_token # note using \_FILE for docker secrets  
# CF\_DNS\_API\_TOKEN: ${CF\_DNS\_API\_TOKEN} # if using .env  
TRAEFIK\_DASHBOARD\_CREDENTIALS: ${TRAEFIK\_DASHBOARD\_CREDENTIALS}  
secrets:  
- cf\_api\_token  
env\_file: .env # use .env  
volumes:  
- /etc/localtime:/etc/localtime:ro  
- /var/run/docker.sock:/var/run/docker.sock:ro  
- /opt/docker/traefik/data/traefik.yml:/traefik.yml:ro  
- /opt/docker/traefik/data/acme.json:/acme.json  
- /opt/docker/traefik/logs:/var/log/traefik  
- /opt/docker/traefik/data/config.yml:/config.yml:ro  
labels:  
- "traefik.enable=true"  
- "traefik.http.routers.traefik.entrypoints=http"  
- "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.mydomain`)"  
- "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK\_DASHBOARD\_CREDENTIALS}"  
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"  
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"  
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"  
- "traefik.http.routers.traefik-secure.entrypoints=https"  
- "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.mydomain`)"  
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"  
- "traefik.http.routers.traefik-secure.tls=true"  
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"  
- "traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain"  
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=\*.mydomain"  
- "traefik.http.routers.traefik-secure.service=api@internal"

secrets:  
cf\_api\_token:  
file: ./cf\_api\_token.txt

networks:  
proxy:  
external: true

traefik.yml  
api:  
dashboard: true  
debug: true  
entryPoints:  
http:  
address: ":80"  
http:  
# middlewares: # uncomment if using CrowdSec - see my video  
# - crowdsec-bouncer@file  
redirections:  
entrypoint:  
to: https  
scheme: https  
https:  
address: ":443"  
# http:  
# middlewares: # uncomment if using CrowdSec - see my video  
# - crowdsec-bouncer@file

# tcp:

# address: ":10000"

# apis:

# address: ":33073"

serversTransport:  
insecureSkipVerify: true  
providers:  
docker:  
endpoint: "unix:///var/run/docker.sock"  
exposedByDefault: false  
file:  
filename: /config.yml # example provided gives A+ rating [SSL Server Test (Powered by Qualys SSL Labs)](https://www.ssllabs.com/ssltest/)  
certificatesResolvers:  
cloudflare:  
acme:  
caServer: [https://acme-v02.api.letsencrypt.org/directory](https://acme-v02.api.letsencrypt.org/directory) # production (default)  
#caServer: [https://acme-staging-v02.api.letsencrypt.org/directory](https://acme-staging-v02.api.letsencrypt.org/directory) # staging (testing)  
email: [myemail@email.com](mailto:myemail@email.com) # Cloudflare email (or other provider)  
storage: acme.json  
dnsChallenge:  
provider: cloudflare # change as required  
disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.  
delayBeforeCheck: 60s # uncomment along with disablePropagationCheck if needed to ensure the TXT record is ready before verification is attempted  
resolvers:  
- "1.1.1.1:53"  
- "1.0.0.1:53"

log:  
level: "ERROR"  
filePath: "/var/log/traefik/traefik.log"  
accessLog:  
filePath: "/var/log/traefik/access.log"

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 1, 2025, 6:59am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/2 "2025-03-01T06:59:43Z")

</div>

Use 3 backticks before and after your code/config to make it more readable and preserve spacing, which is important in yaml.

Check [simple Traefik Swarm example](https://github.com/bluepuma77/traefik-best-practice/tree/main/docker-swarm-traefik-dnschallenge).

Main changes:

1. Switch from `providers.docker` to `providers.swarm`
2. Place labels within `deploy` section
3. Add `loadbalancer.server.port`
4. Use `docker stack deploy`
5. When running multiple Traefik instances, you can’t use LetsEncrypt `httpChallenge` or `tlsChallenge`

Note that Docker Swarm will not create bind mount folders on host, like Docker does when they don’t exist. Also note that volumes are only on the node, they are not replicated to other nodes.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 1, 2025, 9:05am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/3 "2025-03-01T09:05:32Z")

</div>

Thank you!  
Please assume I am a total idiot.  
Would these amendments be correct?

```auto
version: "3.8"

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
      # - 443:443/tcp # Uncomment if you want HTTP3
      # - 443:443/udp # Uncomment if you want HTTP3
    environment:
      CF_DNS_API_TOKEN_FILE: /run/secrets/cf_api_token # note using _FILE for docker secrets
      # CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN} # if using .env
      TRAEFIK_DASHBOARD_CREDENTIALS: ${TRAEFIK_DASHBOARD_CREDENTIALS}
    secrets:
      - cf_api_token
    env_file: .env # use .env
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
      - ./data/logs:/var/log/traefik
      - ./data/config.yml:/config.yml:ro
    command:
      - --providers.swarm.exposedByDefault=false
      - --providers.swarm.network=proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.web.address=:443
      - --entrypoints.websecure.asDefault=true
      - --entrypoints.websecure.http.tls.certresolver=myresolver
      - --entrypoints.websecure.http.tls.domains[0].main=domain.com
      - --entrypoints.websecure.http.tls.domains[0].sans=*.domain.com
      - --certificatesresolvers.myresolver.acme.email=email@email.com
      - --certificatesresolvers.myresolver.acme.storage=/data/acme.json
      - --certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare
    deploy:
      mode: global
      placement:
        constraints:
          - node.role==manager 
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.traefik.entrypoints=http"
        - "traefik.http.services.traefik-secure.loadbalancer.server.port=1337
        - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.domain.com`)"
        - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
        - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
        - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
        - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
        - "traefik.http.routers.traefik-secure.entrypoints=https"
        - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.domain.com`)"
        - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
        - "traefik.http.routers.traefik-secure.tls=true"
        - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
        - "traefik.http.routers.traefik-secure.tls.domains[0].main=domain.com"
        - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.domain.com"
        - "traefik.http.routers.traefik-secure.service=api@internal"

secrets:
  cf_api_token:
    file: ./cf_api_token.txt

networks:
  proxy:
    external: true

```

Also, do I need any changes in the traefik.yml file?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 1, 2025, 9:27am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/4 "2025-03-01T09:27:47Z")

</div>

You can only have one Traefik static config, either `traefik.yml` or `command:` ([doc](https://doc.traefik.io/traefik/getting-started/configuration-overview/#the-static-configuration)), decide for one.

You don’t need the https redirect labels, if redirect is already on web `entrypoint`. Also TLS declaration is enough on websecure `entrypoint`.

And I don’t get it why every newbie comes along with this line, it’s absolutely useless, as it’s set by Traefik automatically:

```auto
customrequestheaders.X-Forwarded-Proto=https

```

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 1, 2025, 1:29pm UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/5 "2025-03-01T13:29:49Z")

</div>

Thank you.  
So if I wish to continue using traefik.yml, how do I adapt the entire command: section needed in my current traefik.yml file?

```auto
api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
serversTransport:
  insecureSkipVerify: true
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /config.yml
certificatesResolvers:
  cloudflare:
    acme:
      email: email@email.com
      storage: acme.json
      caServer: https://acme-v02.api.letsencrypt.org/directory # prod (default)
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory # staging
      dnsChallenge:
        provider: cloudflare
        disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
        delayBeforeCheck: 60s # uncomment along with disablePropagationCheck if needed to ensure the TXT record is ready before verification is attempted 
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

log:
  level: "ERROR"
  filePath: "/var/log/traefik/traefik.log"

```

Also, is it also possible to have just one instance of traefik running for all my hosts?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 1, 2025, 3:18pm UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/6 "2025-03-01T15:18:16Z")

</div>

Sorry, i will not check your config line by line. You can take additional lines from command and work them into traefik.yml. I created the repo to have a best practice starting point.

You can have a single Traefik instance for Swarm. You can pin it to a host with placement constraints, or set `replica: 1`. [Simple example for single manager](https://github.com/bluepuma77/traefik-best-practice/tree/main/docker-swarm-traefik).

When the port/container is not explicitly in network mode "host", then Swarm will create an ingress network and the instance can be reached from any node on the published port.

For a stable Swarm, you should have 3 manager nodes, which will also act as workers.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 2, 2025, 2:11am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/7 "2025-03-02T02:11:58Z")

</div>

Thanks so much!  
Noted on the 3 node swarm requirements  
Would I also need shared storage for the Swarm to be stable? eg an NFS share from truenas?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 2, 2025, 7:31am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/8 "2025-03-02T07:31:43Z")

</div>

Swarm just works. But it has no shared storage.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 10, 2025, 9:17am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/9 "2025-03-10T09:17:04Z")

</div>

> [@bluepuma77](#):
>
> When the port/container is not explicitly in network mode "host", then Swarm will create an ingress network and the instance can be reached from any node on the published port.

DO you mean to remove from here?  
ports:  
- target: 80  
published: 80  
protocol: tcp  
#mode: host  
- target: 443  
published: 443  
protocol: tcp  
#mode: host

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 10, 2025, 10:32am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/10 "2025-03-10T10:32:18Z")

</div>

> [@epicurean](#):
>
> ```auto
> ports:
> - target: 80
> published: 80
> protocol: tcp
> #mode: host
> - target: 443
> published: 443
> protocol: tcp
> #mode: host
> 
> ```

with `mode: host` commented out, the ingress network should be created, and your service should be available on all nodes on the ports.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 14, 2025, 2:40am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/11 "2025-03-14T02:40:24Z")

</div>

I am unable to deploy the stack , with these errors:

```auto
Since --detach=false was not specified, tasks will be created in the background.
In a future release, --detach=false will become the default.
network "proxy" is declared as external, but it is not in the right scope: "loca l" instead of "swarm"

```

My docker-compose.yml :

```auto

services:
  traefik:
    image: traefik:v3.3
    hostname: '{{.Node.Hostname}}'
    networks:
      - proxy
    ports:
      - target: 80
        published: 80
        protocol: tcp
        #mode: host
      - target: 443
        published: 443
        protocol: tcp
        #mode: host
    environment:
      CF_DNS_API_TOKEN_FILE: /run/secrets/cf_api_token # note using _FILE for docker secrets
      # CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN} # if using .env
      TRAEFIK_DASHBOARD_CREDENTIALS: ${TRAEFIK_DASHBOARD_CREDENTIALS}
    secrets:
      - cf_api_token
    env_file: .env # use .env
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # - /opt/docker/traefik/data/traefik.yml:/traefik.yml:ro
      - /opt/docker/traefik/data/acme.json:/acme.json
      - /opt/docker/traefik/logs:/var/log/traefik
      # - /opt/docker/traefik/data/config.yml:/config.yml:ro
    command:
      - --api.dashboard=true
      - --api.debug=true
      - --log.level=DEBUG
      - --log.filepath=/var/log/traefik.log
      - --accesslog=true
      - --accesslog.filepath=/var/log/traefik-access.log
      - --providers.swarm.exposedByDefault=false
      - --providers.swarm.network=proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entryPoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.asDefault=true
      - --entrypoints.websecure.http.tls.certresolver=cloudflare
      # optionally create wildcard cert, without LE will create TLS certs for all `Host()`s
      - --entrypoints.websecure.http.tls.domains[0].main=mydomain.com
      - --entrypoints.websecure.http.tls.domains[0].sans=*.mydomain.com
      - --certificatesresolvers.cloudflare.acme.email=myemail@email.com
      - --certificatesresolvers.cloudflare.acme.storage=acme.json
      - --certificatesresolvers.cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # production
      - --certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
      - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
      - --serversTransport.insecureSkipVerify=true
    deploy:
      mode: global
      replicas: 1
      placement:
        constraints:
          - node.role==manager
      
      restart_policy:
        condition: unless-stopped
        delay: 2s
        max_attempts: 3
        window: 60s
        
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.mydomain.com`)"
        - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
        - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.mydomain.com`)"
        - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
        - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
        - "traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.com"
        - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.mydomain.com"
        - "traefik.http.routers.traefik-secure.service=api@internal"
        - "traefik.http.services.traefik-secure.loadbalancer.server.port=1337"
  whoami:
    image: traefik/whoami:v1.10
    hostname: '{{.Node.Hostname}}'
    networks:
      - proxy
    deploy:
      mode: global
      labels:
        - traefik.enable=true
        - traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)
        - traefik.http.services.whoami.loadbalancer.server.port=80
secrets:
  cf_api_token:
    file: ./cf_api_token.txt

networks:
  proxy:
    name: proxy
    driver: overlay
    attachable: true
    external: true
    

```

I must be missing something?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 14, 2025, 6:52am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/12 "2025-03-14T06:52:13Z")

</div>

> [@epicurean](#):
>
> ```auto
> networks:
> proxy:
> name: proxy
> driver: overlay
> attachable: true
> external: true
> 
> ```

This seems wrong. Either you create the network within the compose project (`driver`, `attachable`), or you use an already existing one (`external`).

And you probably have an old local "proxy" named Docker network on host, you need to remove that (`docker network ls`, `docker network rm proxy`).

Note that you don’t need any TLS settings on `router`/labels, if they are already set globally on `entrypoint`.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 14, 2025, 11:11am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/13 "2025-03-14T11:11:10Z")

</div>

Thank you!  
so i just amend this section like this:

networks:  
proxy:  
name: proxy  
driver: overlay  
attachable: true

Will remove the old local "proxy" network  
What do you mean by TLS settings on router.labels? you mean the 3 lines with .tls in them?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 14, 2025, 12:27pm UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/14 "2025-03-14T12:27:45Z")

</div>

Yes. If TLS is set up globally on `entrypoint` in static config, you don't need to repeat in every dynamic config on every `router`. Check [simple Traefik dnsChallenge example](https://github.com/bluepuma77/traefik-best-practice/tree/main/docker-traefik-dnschallenge).

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 28, 2025, 11:13am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/16 "2025-03-28T11:13:25Z")

</div>

have this error after \* Run `docker stack deploy -c docker-compose.yml myProxy`

Since --detach=false was not specified, tasks will be created in the background.  
In a future release, --detach=false will become the default.  
Creating network proxy  
Creating secret myProxy\_cf\_api\_token  
service traefik: replicas can only be used with replicated or replicated-job mode

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 28, 2025, 11:40am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/17 "2025-03-28T11:40:02Z")

</div>

Share your current compose file.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 28, 2025, 12:31pm UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/18 "2025-03-28T12:31:37Z")

</div>

```auto
services:
  traefik:
    image: traefik:v3.3
    hostname: '{{.Node.Hostname}}'
    networks:
      - proxy
    ports:
      - target: 80
        published: 80
        protocol: tcp
        #mode: host
      - target: 443
        published: 443
        protocol: tcp
        #mode: host
    environment:
      CF_DNS_API_TOKEN_FILE: /run/secrets/cf_api_token # note using _FILE for docker secrets
      # CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN} # if using .env
      TRAEFIK_DASHBOARD_CREDENTIALS: ${TRAEFIK_DASHBOARD_CREDENTIALS}
    secrets:
      - cf_api_token
    env_file: .env # use .env
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # - /opt/docker/traefik/data/traefik.yml:/traefik.yml:ro
      - /opt/docker/traefik/data/acme.json:/acme.json
      - /opt/docker/traefik/logs:/var/log/traefik
      # - /opt/docker/traefik/data/config.yml:/config.yml:ro
    command:
      - --api.dashboard=true
      - --api.debug=true
      - --log.level=DEBUG
      - --log.filepath=/var/log/traefik.log
      - --accesslog=true
      - --accesslog.filepath=/var/log/traefik-access.log
      - --providers.swarm.exposedByDefault=false
      - --providers.swarm.network=proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entryPoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.asDefault=true
      - --entrypoints.websecure.http.tls.certresolver=cloudflare
      # optionally create wildcard cert, without LE will create TLS certs for all `Host()`s
      - --entrypoints.websecure.http.tls.domains[0].main=mydomain.com
      - --entrypoints.websecure.http.tls.domains[0].sans=*.mydomain.com
      - --certificatesresolvers.cloudflare.acme.email=myemail@email.com
      - --certificatesresolvers.cloudflare.acme.storage=acme.json
      - --certificatesresolvers.cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # production
      - --certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
      - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
      - --serversTransport.insecureSkipVerify=true
    deploy:
      mode: global
      replicas: 1
      placement:
        constraints:
          - node.role==manager
      
      restart_policy:
        condition: unless-stopped
        delay: 2s
        max_attempts: 3
        window: 60s
        
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.mydomain.com`)"
        - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
        - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.mydomain.com`)"
        - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
        - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
        - "traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.com"
        - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.mydomain.com"
        - "traefik.http.routers.traefik-secure.service=api@internal"
        - "traefik.http.services.traefik-secure.loadbalancer.server.port=1337"
  whoami:
    image: traefik/whoami:v1.10
    hostname: '{{.Node.Hostname}}'
    networks:
      - proxy
    deploy:
      mode: global
      labels:
        - traefik.enable=true
        - traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)
        - traefik.http.services.whoami.loadbalancer.server.port=80
secrets:
  cf_api_token:
    file: ./cf_api_token.txt

networks:
  proxy:
    name: proxy
    driver: overlay
    attachable: true
    
type or paste code here

```

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 28, 2025, 1:11pm UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/19 "2025-03-28T13:11:36Z")

</div>

> [@epicurean](#):
>
> ```auto
> deploy:
> mode: global
> replicas: 1
> 
> ```

This does not work. Either `mode: global`, so one container on every node, or `replicas:` to determine the number of containers in the whole Swarm.

---

<div class="post-metadata">

**Author:** ![epicurean](https://avatars.discourse-cdn.com/v4/letter/e/7cd45c/32.png) [@epicurean](https://community.traefik.io/u/epicurean)\
**Post date:** [March 29, 2025, 2:26am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/20 "2025-03-29T02:26:14Z")

</div>

thank you.  
Is there a sequence I should follow to prepare for this new configuration, as my current swarm has a single traefik instance on one of the nodes,and the last time disabled it and tried to do a new traefik (with swarm mode modifications), that node could not rejoin the swarm again?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 29, 2025, 7:50am UTC](https://community.traefik.io/t/converting-traefik-from-docker-to-one-that-enables-reverse-proxy-to-docker-swarm/26705/21 "2025-03-29T07:50:08Z")

</div>

You can run regular containers even on Swarm nodes. So you can keep the single Traefik instance running, establish a Swarm, stop the container, start a Docker service.

If it doesn’t work the way you want it, just stop the service and start the single container again. No influence on Swarm.
