├── intranet_dmz ├── zipkin-config.json ├── httpd.conf └── nginx.conf ├── setup-elk.sh ├── traefik.toml ├── management-ui.yml ├── README.md ├── edge.yml ├── management.yml └── intranet.yml /intranet_dmz/zipkin-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "service_name": "nginx", 3 | "collector_host": "zipkin" 4 | } 5 | -------------------------------------------------------------------------------- /setup-elk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker run --rm --network management_default docker.elastic.co/beats/filebeat:7.6.2 setup --index-management -E setup.ilm.overwrite=true -E 'output.elasticsearch.hosts=["elasticsearch:9200"]' 3 | docker run --rm --network management_default docker.elastic.co/beats/filebeat:7.6.2 setup --dashboards -E setup.kibana.host=kibana-api:5601/kibana 4 | docker run --rm --network management_default docker.elastic.co/beats/metricbeat:7.6.2 setup --index-management -E setup.ilm.overwrite=true -E 'output.elasticsearch.hosts=["elasticsearch:9200"]' 5 | docker run --rm --network management_default docker.elastic.co/beats/metricbeat:7.6.2 setup --dashboards -E setup.kibana.host=kibana-api:5601/kibana 6 | -------------------------------------------------------------------------------- /traefik.toml: -------------------------------------------------------------------------------- 1 | [tls.options] 2 | 3 | [tls.options.default] 4 | minVersion = "VersionTLS12" 5 | 6 | cipherSuites = [ 7 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 8 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 9 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 10 | "TLS_AES_128_GCM_SHA256", 11 | "TLS_AES_256_GCM_SHA384", 12 | "TLS_CHACHA20_POLY1305_SHA256" 13 | ] 14 | 15 | sniStrict = true 16 | 17 | [tls.options.intranet] 18 | minVersion = "VersionTLS12" 19 | 20 | cipherSuites = [ 21 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 22 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 23 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 24 | "TLS_AES_128_GCM_SHA256", 25 | "TLS_AES_256_GCM_SHA384", 26 | "TLS_CHACHA20_POLY1305_SHA256" 27 | ] 28 | 29 | sniStrict = true 30 | [tls.options.intranet.clientAuth] 31 | caFiles = ["/ca.pem"] 32 | clientAuthType = "RequireAndVerifyClientCert" 33 | 34 | [http.middlewares] 35 | [http.middlewares.compress-all.compress] 36 | 37 | [http.middlewares.security-headers.headers] 38 | BrowserXssFilter = true 39 | ContentTypeNosniff = true 40 | ForceSTSHeader = true 41 | FrameDeny = true 42 | SSLRedirect = true 43 | STSIncludeSubdomains = true 44 | STSPreload = true 45 | STSSeconds = 315360000 46 | 47 | [http.middlewares.strip-prefix.chain] 48 | middlewares = [ "strip-prefix-1", "strip-prefix-2"] 49 | 50 | [http.middlewares.strip-prefix-1.redirectregex] 51 | regex="^(https?://[^/]+/[a-z0-9_]+)$" 52 | replacement="${1}/" 53 | permanent = true 54 | 55 | [http.middlewares.strip-prefix-2.stripprefixregex] 56 | regex = [ "/[a-z0-9_]+" ] 57 | -------------------------------------------------------------------------------- /intranet_dmz/httpd.conf: -------------------------------------------------------------------------------- 1 | # Settings for an Apache proxy 2 | 3 | ServerName i.trajano.net 4 | ServerAdmin i@trajano.net 5 | ServerRoot /usr/local/apache2 6 | User daemon 7 | Group daemon 8 | 9 | Timeout 10 10 | MaxRequestWorkers 100 11 | 12 | Listen 443 13 | 14 | LoadModule authz_core_module modules/mod_authz_core.so 15 | LoadModule http2_module modules/mod_http2.so 16 | LoadModule log_config_module modules/mod_log_config.so 17 | LoadModule mpm_event_module modules/mod_mpm_event.so 18 | LoadModule socache_shmcb_module modules/mod_socache_shmcb.so 19 | LoadModule ssl_module modules/mod_ssl.so 20 | LoadModule unixd_module modules/mod_unixd.so 21 | 22 | LoadModule proxy_module modules/mod_proxy.so 23 | LoadModule proxy_http_module modules/mod_proxy_http.so 24 | LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so 25 | 26 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 27 | LogLevel warn 28 | CustomLog /proc/self/fd/1 combined 29 | ErrorLog /proc/self/fd/2 30 | DocumentRoot /usr/local/apache2/htdocs 31 | 32 | SSLCipherSuite HIGH:MEDIUM:!SSLv3:!kRSA 33 | SSLProxyCipherSuite HIGH:MEDIUM:!SSLv3:!kRSA 34 | SSLHonorCipherOrder on 35 | SSLProtocol -all +TLSv1.2 +TLSv1.3 36 | SSLProxyProtocol -all +TLSv1.2 +TLSv1.3 37 | SSLPassPhraseDialog builtin 38 | SSLSessionCache "shmcb:/usr/local/apache2/logs/ssl_scache(512000)" 39 | SSLSessionCacheTimeout 300 40 | 41 | 42 | AllowOverride none 43 | Require all denied 44 | 45 | 46 | Protocols h2 http/1.1 47 | 48 | 49 | SSLEngine on 50 | SSLCACertificateFile "/ca.pem" 51 | SSLCertificateFile "/cert.pem" 52 | SSLCertificateKeyFile "/key.pem" 53 | SSLVerifyClient require 54 | SSLVerifyDepth 2 55 | 56 | 57 | Require expr %{SSL_CLIENT_VERIFY} == 'SUCCESS' 58 | ProxyPreserveHost on 59 | ProxyPass "http://proxy/" 60 | ProxyPassReverse "http://proxy/" 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /intranet_dmz/nginx.conf: -------------------------------------------------------------------------------- 1 | load_module modules/ngx_http_opentracing_module.so; 2 | user nginx; 3 | worker_processes 1; 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | events { 7 | worker_connections 1024; 8 | } 9 | http { 10 | opentracing on; 11 | opentracing_load_tracer /usr/local/lib/libzipkin_opentracing_plugin.so /etc/zipkin-config.json; 12 | default_type application/octet-stream; 13 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 14 | '$status $body_bytes_sent "$http_referer" ' 15 | '"$http_user_agent" "$http_x_forwarded_for"'; 16 | access_log /var/log/nginx/access.log main; 17 | server { 18 | listen 443; 19 | ssl on; 20 | server_name i.trajano.net; 21 | ssl_certificate /cert.pem; 22 | ssl_certificate_key /key.pem; 23 | ssl_client_certificate /ca.pem; 24 | ssl_verify_client on; 25 | ssl_trusted_certificate /cert.pem; 26 | ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1; 27 | ssl_prefer_server_ciphers on; 28 | ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS; 29 | location / { 30 | opentracing_propagate_context; 31 | opentracing_trace_locations off; 32 | proxy_set_header Host $host; 33 | proxy_set_header X-Real-IP $remote_addr; 34 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 35 | proxy_set_header X-Forwarded-Proto $scheme; 36 | # proxy_set_header Y-B3-Traceid ; 37 | proxy_pass http://proxy/; 38 | } 39 | location = /w { 40 | opentracing_propagate_context; 41 | opentracing_trace_locations off; 42 | proxy_set_header Host $host; 43 | proxy_pass http://whoami/; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /management-ui.yml: -------------------------------------------------------------------------------- 1 | # docker stack deploy -c management-ui.yml --prune management-ui 2 | version: '3.7' 3 | services: 4 | zipkin_ui: 5 | image: alpine/socat 6 | command: tcp-listen:9411,fork,reuseaddr tcp:zipkin:9411 7 | deploy: 8 | resources: 9 | limits: 10 | cpus: '0.5' 11 | memory: 32M 12 | labels: 13 | - intranet=true 14 | - traefik.enable=true 15 | - traefik.http.routers.zipkin.rule=PathPrefix(`/zipkin`) 16 | - traefik.http.services.zipkin.loadbalancer.server.port=9411 17 | networks: 18 | - intranet 19 | - management-ui 20 | 21 | portainer: 22 | image: portainer/portainer 23 | command: -H tcp://tasks.agent:9001 --tlsskipverify --no-auth 24 | volumes: 25 | - portainer_data:/data 26 | networks: 27 | - intranet 28 | - management-ui 29 | deploy: 30 | labels: 31 | - intranet=true 32 | - traefik.enable=true 33 | - traefik.http.routers.portainer.middlewares=strip-prefix@file 34 | - traefik.http.services.portainer.loadbalancer.server.port=9000 35 | kibana: 36 | image: alpine/socat 37 | command: tcp-listen:5601,fork,reuseaddr tcp:kibana-api:5601 38 | deploy: 39 | resources: 40 | limits: 41 | cpus: '0.5' 42 | memory: 32M 43 | labels: 44 | - intranet=true 45 | - traefik.enable=true 46 | - traefik.http.routers.kibana.rule=PathPrefix(`/kibana`) 47 | - traefik.http.routers.kibana.service=kibana 48 | - traefik.http.services.kibana.loadbalancer.server.port=5601 49 | networks: 50 | - intranet 51 | - management-ui 52 | # kibana: 53 | # image: docker.elastic.co/kibana/kibana:7.5.2 54 | # environment: 55 | # - SERVER_BASEPATH=/kibana 56 | # - SERVER_REWRITEBASEPATH=true 57 | # ports: 58 | # - 5601:5601 59 | # networks: 60 | # - intranet 61 | # - management-ui 62 | # deploy: 63 | # labels: 64 | # - intranet=true 65 | # - traefik.enable=true 66 | # - traefik.http.routers.kibana.entryPoints=http 67 | # - traefik.http.services.kibana.loadbalancer.server.port=5601 68 | # # labels: 69 | # # co.elastic.logs/module: kibana 70 | # # co.elastic.logs/fileset: log 71 | 72 | networks: 73 | intranet: 74 | external: true 75 | management-ui: 76 | external: true 77 | 78 | volumes: 79 | portainer_data: 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trajano base Docker swarm stacks 2 | 3 | This contains the stack files used to deploy my Docker swarm. It uses Traefik 2.2 to do the TLS routing and SSL termination and client certificate validation and another Traefik to manage the intranet services. 4 | 5 | It uses the label `intranet=true` to distinguish intranet services from external services. 6 | 7 | In addition, this has a management plane which provides Zipkin and Portainer agents and a management UI stack exposed to the intranet to access the necessary info. 8 | 9 | Due to Traefik only not allowing TLS options to be set in Docker labels, a TOML file containing the configuration is needed in order to at least get to **SSLLabs A rating**. This configuration file `traefik.toml` contains common middlewares that apply to both public and intranet traefiks. The `/ping` endpoint is where I stored the labels used to dynamically configure the Docker provider that are specific to the environment. 10 | 11 | ## Common middlewares 12 | 13 | * `compress-all` which provides compression. 14 | * `security-headers` which provides additional headers to [push Trajano.net SSLLabs to A+ rating](https://www.ssllabs.com/ssltest/analyze.html?d=trajano.net) 15 | * `strip-prefix` which strips the prefix and does a redirect if the first segment does not end with `/` which is useful for reverse proxies that have a single DNS with top level path per application. 16 | 17 | The `default` middleware chain for public is `https-only@file,security-headers@file,compress-all@file` 18 | 19 | The `default` middleware chain for intranet is `compress-all@file` since it is expected the internal services are HTTP only from the point of view of the Apache proxy. 20 | 21 | ## Required files 22 | 23 | The mappings to the following file should change to match your Intranet CA and the traefik configuration file respectively. 24 | 25 | - /d/p/trajano.net/devops-ca-R2.crt 26 | - /d/p/trajano.net/traefik.toml 27 | 28 | ## Deploying 29 | 30 | ``` 31 | docker stack deploy -c management.yml --prune management 32 | docker stack deploy -c edge.yml --prune edge 33 | docker stack deploy -c intranet.yml --prune intranet 34 | docker stack deploy -c management-ui.yml --prune management-ui 35 | ``` 36 | 37 | ## Notes 38 | 39 | * External dashboard is exposed to `44444` for now until https://github.com/containous/traefik/issues/5853 which will allow a second dashboard and API endpoint on the same domain. 40 | * Intranet dashboard is exposed to "/traefik" based on comment by https://github.com/containous/traefik/issues/5853#issuecomment-575290336. 41 | * `setup-elk.sh` configures the ELK stack after it has been deployed. 42 | 43 | ## DMZs 44 | 45 | In the most recent refactoring, having an intermediate DMZ server was removed and now it is Traefik to Traefik communication for the intranet. However, this approach prevents having complex rules or transformations that would've been possible with either Apache or nginx. 46 | 47 | ## Branches 48 | * [apache](https://github.com/trajano/trajano-swarm/tree/apache) uses Apache HTTPd as the DMZ. 49 | * [nginx](https://github.com/trajano/trajano-swarm/tree/nginx) uses nginx as the DMZ. 50 | -------------------------------------------------------------------------------- /edge.yml: -------------------------------------------------------------------------------- 1 | # docker stack deploy -c edge.yml --prune edge 2 | version: "3.7" 3 | services: 4 | traefik: 5 | image: traefik:v2.2 6 | ports: 7 | - target: 80 8 | published: 80 9 | protocol: tcp 10 | # mode: host 11 | - target: 443 12 | published: 443 13 | protocol: tcp 14 | # mode: host 15 | - target: 8080 16 | published: 44444 17 | protocol: tcp 18 | # mode: host 19 | command: 20 | - --global.checknewversion=false 21 | - --global.sendanonymoususage=false 22 | 23 | - --accesslog 24 | - --accesslog.fields.headers.defaultmode=keep 25 | - --api 26 | - --api.insecure 27 | - --ping 28 | 29 | - --certificatesResolvers.default.acme.tlsChallenge=true 30 | - --certificatesresolvers.default.acme.email=support@trajano.net 31 | - --certificatesresolvers.default.acme.storage=/etc/traefik/acme/default.json 32 | 33 | - --entrypoints.http.address=:80 34 | - --entrypoints.http.http.redirections.entryPoint.to=https 35 | - --entrypoints.http.http.redirections.entryPoint.scheme=https 36 | - --entrypoints.http.http.redirections.entrypoint.permanent=true 37 | 38 | - --entrypoints.https.address=:443 39 | - --entrypoints.https.http.middlewares=security-headers@file,compress-all@file 40 | - --entrypoints.https.http.tls.certresolver=default 41 | - --entrypoints.https.http.tls.options=default 42 | 43 | - --providers.docker.endpoint=tcp://daemon:2375 44 | - --providers.docker.exposedByDefault=false 45 | - --providers.docker.swarmMode=true 46 | - "--providers.docker.constraints=!Label(`intranet`, `true`)" 47 | - '--providers.docker.defaultrule=Host(`trajano.net`) && PathPrefix(`/{{ .Name | trimPrefix (index .Labels "com.docker.stack.namespace") | trimPrefix "_" | trimPrefix "-" }}`)' 48 | 49 | - --providers.file.filename=/traefik-conf.toml 50 | 51 | - --tracing.zipkin.httpEndpoint=http://zipkin:9411/api/v2/spans 52 | 53 | healthcheck: 54 | test: traefik healthcheck --ping 55 | volumes: 56 | - letsencrypt:/etc/traefik/acme 57 | - /d/p/trajano.net/devops-ca-R2.crt:/ca.pem 58 | - /d/p/trajano.net/traefik.toml:/traefik-conf.toml 59 | networks: 60 | - traefik 61 | - default 62 | - management 63 | labels: 64 | co.elastic.logs/module: traefik 65 | co.elastic.logs/fileset.stdout: access 66 | co.elastic.logs/fileset.stderr: error 67 | deploy: 68 | # mode: global 69 | restart_policy: 70 | condition: any 71 | delay: 10s 72 | resources: 73 | limits: 74 | memory: 64M 75 | cpus: "1.0" 76 | reservations: 77 | memory: 16M 78 | daemon: 79 | image: tecnativa/docker-socket-proxy 80 | volumes: 81 | - /var/run/docker.sock:/var/run/docker.sock:ro 82 | environment: 83 | NETWORKS: 1 84 | SERVICES: 1 85 | TASKS: 1 86 | labels: 87 | - co.elastic.logs/enabled=false 88 | deploy: 89 | mode: global 90 | placement: 91 | constraints: 92 | - node.role == manager 93 | resources: 94 | limits: 95 | cpus: '0.5' 96 | memory: 32M 97 | networks: 98 | default: 99 | internal: true 100 | attachable: false 101 | traefik: 102 | name: traefik 103 | internal: true 104 | attachable: true 105 | management: 106 | external: true 107 | volumes: 108 | letsencrypt: 109 | -------------------------------------------------------------------------------- /management.yml: -------------------------------------------------------------------------------- 1 | # docker stack deploy -c management.yml --prune management 2 | version: "3.7" 3 | services: 4 | zipkin: 5 | image: openzipkin/zipkin:2.21.1 6 | environment: 7 | - STORAGE_TYPE=elasticsearch 8 | - ES_HOSTS=http://elasticsearch:9200 9 | networks: 10 | - management 11 | - management-ui 12 | - default 13 | deploy: 14 | resources: 15 | limits: 16 | cpus: '0.5' 17 | memory: 128M 18 | 19 | elasticsearch: 20 | image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2 21 | ports: 22 | - 9200:9200 23 | environment: 24 | - "discovery.type=single-node" 25 | - "logger.org.elasticsearch=error" 26 | - "xpack.security.enabled=false" 27 | - "xpack.monitoring.enabled=false" 28 | volumes: 29 | - elasticsearch-data:/usr/share/elasticsearch/data 30 | labels: 31 | co.elastic.logs/enabled: "true" 32 | co.elastic.logs/module: elasticsearch 33 | co.elastic.logs/fileset.stdout: server 34 | deploy: 35 | resources: 36 | limits: 37 | memory: 1G 38 | agent: 39 | image: portainer/agent 40 | environment: 41 | AGENT_CLUSTER_ADDR: tasks.agent 42 | volumes: 43 | - /var/run/docker.sock:/var/run/docker.sock 44 | - /var/lib/docker/volumes:/var/lib/docker/volumes 45 | networks: 46 | - management-ui 47 | deploy: 48 | mode: global 49 | placement: 50 | constraints: [node.platform.os == linux] 51 | filebeat: 52 | image: docker.elastic.co/beats/filebeat:7.6.2 53 | deploy: 54 | mode: global 55 | command: 56 | - -E 57 | - | 58 | filebeat.autodiscover.providers=[ 59 | { 60 | type: docker, 61 | hints.enabled: true 62 | } 63 | ] 64 | - -E 65 | - processors={1:{add_docker_metadata:{host:unix:///var/run/docker.sock}}} 66 | - -E 67 | - output.elasticsearch.enabled=true 68 | - -E 69 | - output.elasticsearch.hosts=["elasticsearch:9200"] 70 | - -E 71 | - output.logstash.enabled=false 72 | - --modules 73 | - nginx,mysql,system,traefik,kibana,logstash 74 | # - -d 75 | # - autodiscover 76 | # - -e 77 | user: root 78 | labels: 79 | co.elastic.logs/enabled: "false" 80 | volumes: 81 | - /var/run/docker.sock:/var/run/docker.sock:ro 82 | - /var/lib/docker/containers:/var/lib/docker/containers:ro 83 | metricbeat: 84 | image: docker.elastic.co/beats/metricbeat:7.6.2 85 | volumes: 86 | - /var/run/docker.sock:/var/run/docker.sock:ro 87 | - /sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro 88 | - /proc:/hostfs/proc:ro 89 | - /:/hostfs:ro 90 | user: root 91 | hostname: "{{.Node.Hostname}}" 92 | command: 93 | - -E 94 | - | 95 | metricbeat.modules=[ 96 | { 97 | module:docker, 98 | hosts:[unix:///var/run/docker.sock], 99 | period:10s, 100 | enabled:true 101 | } 102 | ] 103 | - -E 104 | - processors={1:{add_docker_metadata:{host:unix:///var/run/docker.sock}}} 105 | - -E 106 | - output.elasticsearch.enabled=true 107 | - -E 108 | - output.elasticsearch.hosts=["elasticsearch:9200"] 109 | - -E 110 | - output.logstash.enabled=false 111 | deploy: 112 | mode: global 113 | kibana-api: 114 | image: docker.elastic.co/kibana/kibana:7.5.2 115 | environment: 116 | - SERVER_BASEPATH=/kibana 117 | - SERVER_REWRITEBASEPATH=true 118 | - LOGGING_SILENT=true 119 | networks: 120 | - default 121 | - management-ui 122 | deploy: 123 | labels: 124 | co.elastic.logs/module: kibana 125 | co.elastic.logs/fileset: log 126 | 127 | networks: 128 | management: 129 | name: management 130 | internal: true 131 | attachable: true 132 | management-ui: 133 | name: management-ui 134 | internal: true 135 | attachable: true 136 | default: 137 | internal: true 138 | attachable: true 139 | volumes: 140 | elasticsearch-data: 141 | -------------------------------------------------------------------------------- /intranet.yml: -------------------------------------------------------------------------------- 1 | # docker stack deploy -c intranet.yml --prune intranet 2 | version: "3.7" 3 | services: 4 | dmz: 5 | image: traefik:v2.2 6 | command: 7 | - --global.checknewversion=false 8 | - --global.sendanonymoususage=false 9 | 10 | - --accesslog 11 | - --accesslog.fields.headers.defaultmode=keep 12 | - --api 13 | - --ping 14 | 15 | - --entrypoints.http.address=:80 16 | - --entrypoints.http.http.middlewares=compress-all@file 17 | - --entryPoints.http.forwardedHeaders.insecure 18 | 19 | - --providers.docker.endpoint=tcp://daemon:2375 20 | - --providers.docker.exposedByDefault=false 21 | - --providers.docker.swarmMode=true 22 | - --providers.docker.network=intranet 23 | - "--providers.docker.constraints=Label(`intranet`, `true`)" 24 | - '--providers.docker.defaultrule=Host(`i.trajano.net`) && PathPrefix(`/{{ .Name | trimPrefix (index .Labels "com.docker.stack.namespace") | trimPrefix "_" | trimPrefix "-" }}`)' 25 | 26 | - --providers.file.filename=/traefik-conf.toml 27 | 28 | - --tracing.zipkin.httpEndpoint=http://zipkin:9411/api/v2/spans 29 | - --tracing.serviceName=i-traefik 30 | healthcheck: 31 | test: traefik healthcheck --ping 32 | labels: 33 | co.elastic.logs/module: traefik 34 | co.elastic.logs/fileset.stdout: access 35 | co.elastic.logs/fileset.stderr: error 36 | deploy: 37 | update_config: 38 | order: start-first 39 | restart_policy: 40 | condition: any 41 | delay: 10s 42 | resources: 43 | limits: 44 | memory: 64M 45 | cpus: "1.0" 46 | reservations: 47 | memory: 16M 48 | labels: 49 | - traefik.enable=true 50 | - traefik.docker.network=traefik 51 | 52 | - traefik.http.routers.intranet.rule=Host(`i.trajano.net`) 53 | - traefik.http.routers.intranet.entrypoints=https 54 | - traefik.http.routers.intranet.tls.options=intranet@file 55 | - traefik.http.routers.intranet.tls.certresolver=default 56 | - traefik.http.routers.intranet.service=intranet 57 | - traefik.http.services.intranet.loadbalancer.server.port=80 58 | volumes: 59 | - /d/p/trajano.net/traefik.toml:/traefik-conf.toml 60 | networks: 61 | - intranet 62 | - traefik 63 | - internal 64 | - management 65 | daemon: 66 | image: tecnativa/docker-socket-proxy 67 | volumes: 68 | - /var/run/docker.sock:/var/run/docker.sock:ro 69 | networks: 70 | - internal 71 | environment: 72 | NETWORKS: 1 73 | SERVICES: 1 74 | TASKS: 1 75 | labels: 76 | - co.elastic.logs/enabled=false 77 | deploy: 78 | mode: global 79 | placement: 80 | constraints: 81 | - node.role == manager 82 | resources: 83 | limits: 84 | cpus: '0.5' 85 | memory: 32M 86 | ping: 87 | image: alpine/socat 88 | command: tcp-listen:8080,fork,reuseaddr tcp:proxy:8080 89 | deploy: 90 | resources: 91 | limits: 92 | cpus: '0.5' 93 | memory: 32M 94 | labels: 95 | - intranet=true 96 | - traefik.enable=true 97 | - traefik.http.routers.ping.rule=Path(`/ping`) 98 | - traefik.http.routers.ping.service=ping 99 | - traefik.http.services.ping.loadbalancer.server.port=8080 100 | 101 | - traefik.http.routers.traefik.rule=(PathPrefix(`/traefik`) || PathPrefix(`/api`)) 102 | - traefik.http.routers.traefik.service=api@internal 103 | - traefik.http.routers.traefik.middlewares=traefik-strip 104 | - traefik.http.middlewares.traefik-strip.stripprefix.prefixes=/traefik 105 | networks: 106 | - intranet 107 | whoami: 108 | image: containous/whoami 109 | deploy: 110 | resources: 111 | limits: 112 | cpus: '0.5' 113 | memory: 32M 114 | labels: 115 | - intranet=true 116 | - traefik.enable=true 117 | - traefik.http.routers.whoami.middlewares=strip-prefix@file 118 | - traefik.http.services.whoami.loadbalancer.server.port=80 119 | networks: 120 | - intranet 121 | # db: 122 | # image: mysql:8 123 | # environment: 124 | # MYSQL_DATABASE: admin 125 | # MYSQL_USER: admin 126 | # MYSQL_PASSWORD: admin 127 | # MYSQL_ROOT_PASSWORD: admin 128 | # MYSQL_ROOT_HOST: db.trajano.net 129 | # networks: 130 | # - traefik 131 | # deploy: 132 | # labels: 133 | # - traefik.enable=true 134 | # - traefik.docker.network=traefik 135 | # - traefik.tcp.routers.db.rule=HostSNI(`db.trajano.net`) 136 | # - traefik.tcp.routers.db.entrypoints=https 137 | # - traefik.tcp.routers.db.tls.options=intranet@file 138 | # - traefik.tcp.routers.db.tls.certresolver=default 139 | # - traefik.tcp.routers.db.tls.passthrough=false 140 | # - traefik.tcp.routers.db.service=db 141 | # - traefik.tcp.services.db.loadbalancer.server.port=3306 142 | # db: 143 | # image: postgres 144 | # environment: 145 | # POSTGRES_USER: postgres 146 | # POSTGRES_PASSWORD: password1 147 | # networks: 148 | # - traefik 149 | # deploy: 150 | # labels: 151 | # - traefik.enable=true 152 | # - traefik.docker.network=traefik 153 | # - traefik.tcp.routers.db.rule=HostSNI(`db.trajano.net`) 154 | # - traefik.tcp.routers.db.entrypoints=https 155 | # - traefik.tcp.routers.db.tls.options=intranet@file 156 | # - traefik.tcp.routers.db.tls.certresolver=default 157 | # - traefik.tcp.routers.db.service=db 158 | # - traefik.tcp.services.db.loadbalancer.server.port=5432 159 | networks: 160 | traefik: 161 | external: true 162 | intranet: 163 | external: true 164 | management: 165 | external: true 166 | internal: 167 | internal: true 168 | attachable: false 169 | --------------------------------------------------------------------------------