Wowu / docker-rollout

🚀 Zero Downtime Deployment for Docker Compose
https://github.com/Wowu/docker-rollout
MIT License
2.18k stars 59 forks source link

I'd like to request a minimal example demonstrating how to perform zero-downtime deployment using docker rollout with Nginx and Rails. #9

Closed activeliang closed 1 year ago

activeliang commented 1 year ago
version: "3.9"
services:
  web:
    image: activeliang/rtr_wms-web
    environment:
      VITE_RUBY_HOST: 0.0.0.0
      RAILS_ENV: production
    volumes:
      - /tmp/sockets/rtr_wms:/rtr_wms/tmp/sockets

Hello, the code above is part of my docker-compose.yml file, where my Nginx server runs on the host machine and the Rails application runs inside a container. When I specify to scale the Rails application to two instances using the docker rollout, they both point to /rtr_wms/tmp/sockets/puma.sock which causes a conflict, and one of the apps restarts as a result.

My issue is that I'm not sure how to balance the relationship between Nginx and Rails. Therefore, I'd like to request a minimal example demonstrating how to perform zero-downtime deployment using docker rollout with Nginx and Rails.

activeliang commented 1 year ago

My current approach to solving the sock file conflict caused by multiple Rails instances is to use random sock file names. Then, I use a script to update the sock path in Nginx's upstream configuration to achieve load balancing. This is a personal solution, and while it works, I find the implementation somewhat complex. I'm curious if there is a simpler or more streamlined approach available.

Wowu commented 1 year ago

I recommend using Traefik or nginx-proxy as they integrate with docker quite nicely, and you can check out sample compose files in https://github.com/Wowu/docker-rollout/tree/main/examples. docker-rollout was designed to work with proxies using docker events to route traffic to healthy containers.

If you need to run nginx on the host, your solution is quite clever and I don't think I can suggest anything much better. Maybe you can bind your Rails app to :3000 in the container, and use docker inspect to get container ip in your script:

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' CONTAINER_ID
#=> 172.18.0.2

and generate nginx config like this:

proxy_pass http://172.18.0.2:3000;

but this would require some modifications to docker-rollout to update the config after starting new container.

activeliang commented 1 year ago

Thank you for your response. Your suggestion is more convenient than my current approach, and I appreciate it!

Wowu commented 1 year ago

Happy to help!