0

I have a docker-compose based application which I am deploying to production server. Two of its containers share a directories contents using a data volume like so:

...
services:
  service1:
    volumes:
      - server-files:/var/www

  service2:
    volumes:
      - server-files:/var/www

  db:
    volumes:
      - db-persistent:/var/lib/mysql


volumes:
  server-files:
  db-persistent:

The service1's /var/www is populated when its Dockerfile is built. My understanding is that if I make changes to code stored in /var/ww when I rebuild service1 its updates will be hidden by the existing server-files volume.

What is the correct way to update this deployment so that changes propagate with minimal downtime and without deleting other volumes?

Edit

Just to clarify my current deploy process works as follows:

  1. Update code locally and and commit/push changes to Github
  2. Pull changes on server
  3. Run docker-compose build to rebuild any changed containers
  4. Run docker-compose up -d to reload any updated containers

The issue is that changed code within /var/www is hidden by the already existing named volume server-files. My question is what is the best way to handle this update?

Dovid Gefen
  • 323
  • 3
  • 17
  • Does this answer your question? [Docker Compose - Share named volume between multiple containers](https://stackoverflow.com/questions/44284484/docker-compose-share-named-volume-between-multiple-containers) – Alex Aug 13 '20 at 14:13
  • No, I have no issue with how to set up named volumes in docker-compose. My issue is how to deploy code changes to files that are located within existing volume in production. – Dovid Gefen Aug 13 '20 at 14:31
  • So something like updating a MySQL dump (or something similar) through a CI/CD? – Marko E Aug 13 '20 at 15:00

2 Answers2

2

I ended up handling this by managing the databases volume db-persistent outside of
docker-compose. Before running docker-compose up I created the volume manually by running
docker volume create db-persistent and in docker-compose.yml I marked the volume as external with the following configuration:

volumes:
  db-persistent:
    external: true

My deploy process now looks as follows:

  1. Pull changes from Github
  2. Run docker-compose build to automatically build any changed containers.
  3. Shutdown existing application and remove volumes by running docker-compose down -v
  4. Run docker-compose up to start application again.

In this new setup running docker-compose down -v only removes the server-files volume leaving the
db-persistent volume untouched.

Dovid Gefen
  • 323
  • 3
  • 17
2

First of all, docker-compose isn't meant for production deployment. This issue illustrates one of the reasons why: no automatic rolling upgrades. Creating a single node swarm would make your life easier. To deploy, all you would have to do is run docker stack deploy -f docker-compose.yml. However, you might have to tweak your compose file and do some initial setup.

Second of all, you are misunderstanding how docker is meant to be used. Creating a volume binding for your application code is only a shortcut that you do in development so that you don't have to rebuild your image every time you change your code. When you deploy your application however, you build a production image of your application that contains all the code needed to run.

Once this production image is built, you push it up to an image repository (probably docker hub). Your production server pulls the image from that repository, and uses it to create a container that runs your application.

IF you're pulling your application code from your production server, then why use Docker at all? In that scenario, it's just making your life harder and adding extra steps when you could just run everything directly on your host VM and make a simple script to stop your apps, pull your code, and restart your apps.

Charles Desbiens
  • 879
  • 6
  • 14
  • Its not using a volume mounted to host but rather a named volume, in this case I am using it to share a directory between two services. Do you think that even named volumes should not be used in production? What about using a named volume to persist database data, how would you persist it without using a named volume in production? – Dovid Gefen Aug 18 '20 at 11:04
  • Volumes are meant to store persistent data. So every database needs to use a volume if it wants to keep its data. I'm not saying that you shouldn't use volumes in production. I'm saying that they shouldn't contain application code, and that your images should always contain all the code that they need to run. If your two services share some code, then the way to handle that would be to export that code as a library, and install that library in each service separately. – Charles Desbiens Aug 18 '20 at 20:24