2

I have a small group of computers to which I deploy my app with

sudo docker stack deploy --compose-file docker-compose-distributed.yml QC --with-registry-auth

I have one master (?) that runs the website, a database service and two (or more) workers for job scheduling and an S3 data storage. I added constraints so that the webserver is only started on one computer.

I can then see the containers are running, but at the moment there is no way to reach them via http. When I run all containers on the same computer with

sudo docker-compose up

I can simply browse to localhost:8000. But for the docker stack deploy setup, I think, I need something that is called a bridge network or interim network. I am new to docker, so I am not sure which is the correct terminology or which is the right network to setup here?

My setup looks like this:

enter image description here

Now, I need a way to connect this to the outside world i.e. make the website accessible via http.

The website container exposes port 8000.

version: "3.8"

volumes:
  s3data:
    driver: local

services:
  web:
    image: web
    build: .
    env_file:
      - ./.env
    environment:
      - ENVIRONMENT=develop
      - SERVICE_PORTS=8000
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - s3data:/datalake/

    ports:
      - 8000:8000

    depends_on:
      - db
      - redis
      - s3vol
    links:
      - redis:redis
    restart: always
    deploy:
      placement:
        constraints:
          - node.role == manager
  db:
    image: postgres
    volumes:
      - ./data/db/:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=...
      - POSTGRES_USER=...
      - POSTGRES_PASSWORD=...
    deploy:
      placement:
        constraints:
          - node.role == manager
  redis:
    restart: always
    image: redis:alpine
    ports:
      - "6379:6379"
    deploy:
      placement:
        constraints:
          - node.role == manager

  celery:
    restart: on-failure
    image: celery
    build:
      context: .
      dockerfile: Dockerfile
    command: bash -c "celery -A main worker -l info --concurrency ${CONCURRENCY}"
    env_file:
      - ./.env
    volumes:
      - s3data:/datalake/
    environment:
      - DB_HOST=db
      - DB_NAME=app
      - DB_USER=postgres
      - DB_PASS=postgres
    depends_on:
      - db
      - redis
      - web
      - s3vol
    deploy:
      replicas: 1
      placement:
        max_replicas_per_node: 1
        constraints:
          - node.role == manager

  s3vol:
    image: elementar/s3-volume
    command: /data s3://ProteomicsQC
    environment:
      - BACKUP_INTERVAL=2
      - AWS_ACCESS_KEY_ID=...
      - AWS_SECRET_ACCESS_KEY=...
      - ENDPOINT_URL=...
    volumes:
      - s3data:/data
    deploy:
      placement:
        constraints:
          - node.role == manager
3
  • What makes you say the website is not accessible? Did you publish the port? What does the compose file look like and what errors do you see when attempting to connect? Does the error change if you try to connect from the node where the web server is deployed?
    – BMitch
    Sep 9 at 20:22
  • When I start the stack and navigate to localhost:8000 there is nothing. I added the compose file for a development server. Maybe it is accessible via a different IP address?
    – Soren
    Sep 12 at 17:50
  • A blank page indicates you are likely talking to the application and the application itself is having issues. If there's an error page, which error you see is an important detail.
    – BMitch
    Sep 15 at 22:48
2

First of all, thanks for the drawing so I understand what you are trying.

The next step is, when you are working with Docker Swarm all your stacks/services can hit the external networks like Redis, SQL and S3 storage so that is nothing you need to take care of.

When you want traffic inside your cluster you need a proxy in the front, I personally are using NGINX as proxy layer and then you need to create a upstream with a stack of IP's to your Docker Swarm Manager nodes, never sending it to your workers.

Docker Swarm working the way you are sending traffic to a single port number eg. 9000 and this port 9000 is binding to your stack/services on port 80 or what you are needed. Every single replicate will now running on port 9000 for externel traffic from the managers and into your cluster.

Besure you are deploying your stacks only for worker nodes except if its controller software you needed, else you can get a unstable cluster based on my own expires.

If your Redis and SQL running in the cluster (i hope not) but if you want it, you can setup a network for thoes stacks and the add the network internel into your orther stacks, but i will recommend to keep Redis, SQL and somthing like that on the own servers

So the following up on my description here is you need the following.

  • HTTP / HTTPS Proxy to route traffic into a custom port eg. 9000 for your Docker Swarm Managers
  • Expose a port eg. 9000 to your service port eg. 80
  • Setup connection inside the service to use the external Redis and SQL

Thats it, hope i have explain it good enough else you can just ask :)

Expose sample - Docker

docker run -p 9000:6379 –name redis_cont -d redis

allow port 9000 on your host to route into the redis_cont on port 6379

Expose sample - docker-compose.yml

version: "3.7"
services:

 redis:
    image: "redis:alpine"
    ports:
     - "9000:6379"

Deploy a redis stack into your Docker Swarm and allow port 9000 on your host(Docker Swarm Cluster) to route into the Redis stack service on port 6379

4
  • Thank you a lot I really appreciate your effort. I like to have Redis and SQL inside the stack. My primary objective is simplicity. And these things can be changed anytime for production settings. The answer gives some overview about what needs to be done, though it does not offer specific code examples for the docker-compose file. Or links to corresponding examples. And the essential part of the question is rephrased as Expose a port eg. 9000 to your service port eg. 80, The core of the question is how to do exactly that. If you want to elaborate on this, would be great.
    – Soren
    Sep 9 at 19:33
  • I have updated with 2 samples one for docker and secound for docker-compose.yml, hopes what you need. Sep 9 at 20:15
  • Are you sure that works for docker stack deploy? I know this works when I start docker compose on one machine. But when that is started with docker stack deploy I first need a connection into the sub-network. All the services see each other, that is not the question. The question is how to create this overlay or bridge network. The services can reach the outside, but the outside cannot reach the web server.
    – Soren
    Sep 10 at 0:02
  • Even when I create the NGINX one I still need a route to the NGINX service. From outside, not inside the network.
    – Soren
    Sep 10 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.