Search code examples
dockerkubernetesdocker-composedocker-swarm

Zero Down Time Deployment Node.js/NGINX Docker


I have a React/Node.js application running on a single server using docker-compose. I'm trying to achieve a 0 downtime deployment for my react app. The process right now, does a webpack build (replaces the files in my dist folder) and then docker down and docker up. This whole process takes about 2-3 minutes.

I realized that with docker-compose I can scale my container up/down but I'm not sure how to only push my code to 1 of them, rebuild the webpack and npm restart it then kill other containers. I really don't want to use Kubernetes/Swarm or Openshift since it's a bit of overkill. I'm wondering if anyone else has achieved something similar to this.

My docker-compose looks like this:

node:
    build:
        context: ./env/docker/node
        args:
            - PROJECT_ROOT=/var/www/app
    image: react_app:rapp_node
    command: "npm run prod"
    expose:
        - "3333"
    networks:
        - react-net
    volumes_from:
        - volumes_source
    tty: false

nginx:
    env_file:
        - ".env"
    build:
        context: ./env/docker/nginx
    volumes_from:
        - volumes_source
    volumes:
        - ./env/data/logs/nginx/:/var/log/nginx
        - ./env/docker/nginx/sites/node.template:/etc/nginx/node.template
    networks:
        - react-net
        - nginx-proxy
    environment:
        NGINX_HOST: ${NGINX_HOST}
        VIRTUAL_HOST: ${NGINX_VIRTUAL_HOST}
        LETSENCRYPT_HOST: ${NGINX_VIRTUAL_HOST}
        ESC: $$
    links:
        - node:node
    command: /bin/sh -c "envsubst < /etc/nginx/node.template > /etc/nginx/sites-available/node.conf && nginx -g 'daemon off;'"

volumes_source:
    image: tianon/true
    volumes:
        - ./app:/var/www/app

And my nginx is something like this:

server {
server_name www.${NGINX_HOST};
return 301 ${ESC}scheme://${NGINX_HOST}${ESC}request_uri;
}

server {
listen 80;
server_name ${NGINX_HOST};

root /var/www/app;

location / {
proxy_pass http://node:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade ${ESC}http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host ${ESC}host;
proxy_cache_bypass ${ESC}http_upgrade;
}
}

Solution

  • faster way how to refresh container is

    docker-compose restart node
    

    because if you do docker-compose down it will bring all services down, remove configured networks.

    If you have scaled service you might try to restart it with

    docker restart foldername_node_2
    

    and you could have 0 downtime, but the nginx configuration is not sufficient cause it will randomly select node machine, so you will have to implement some backup server