Search code examples
dockerdocker-composeproduction

Building multi-container docker image on server with docker-compose


I'm working on a multi-service docker image which is working fine locally, but having trouble building it server-side (likely a knowledge gap). One service is running my mysql database while the other is my main application (each with their own Dockerfile, though I suppose that's a given), both linked through docker-compose and using depends_on to run setup mysql first and ensure it's in a healthy state.

I've succeeded in building and running the image locally, and have pulled it to the server after pushing to docker hub, but can't find any guidance on how to properly use my docker-compose.yml file in production. It took me a while to realise I'd need to upload the docker-compose file to production separately, but now I'm puzzled about the 'build' settings.

Locally, I'm using a docker-compose.yml file similar to the one below, with the 'build' setting pointing to the db_config folder in the project directory.

version: '2.1'
services:
    mysql:
        image: username/my_image:latest
        container_name: db
        build: ./db_config
        environment:
            MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
            MYSQL_USER: "dbuser"
            MYSQL_PASSWORD: "12345"
            MYSQL_DATABASE: "my_db"
        healthcheck:
            test: "exit 0"

    my_app:
        container_name: app
        build: .
        depends_on:
            mysql:
                condition: service_healthy
        entrypoint:
            - /usr/local/bin/docker-entrypoint.sh
        ports:
            - "80:8080"

Trying to build (docker-compose build) using this file on production gives the following error (names changed):

build path /home/user/my_app/db_config either does not exist, is not accessible, or is not a valid URL.

What should 'build' point to in production? Should I somehow be pointing to the Dockerfile in the docker image itself, or should this config be completely different in production? Do any other configurations need changing too?


Solution

  • The thing is that you shouldn't build a docker image for production.

    The usual setup is that you build an image that can run on multiple environments. On UAT you test this image and when it's ok, you make the production environment to stop current containers and then you start new ones based on the new image.

    To store the image, you can use i.e. docker registry.

    As for your errors, they're happening because on the machine where you execute docker-compose build you do not have the db_config file. Similar to the necessity to upload compose to production, in order to build an image on the production environment, you need to provide all necessary project files that are needed for the build.

    If you want to make it "clean" then the proper way is to build an image on build environment, push the image to the registry and then on the production just do the deployment.

    And yes, for the production deployment you need the compose file. However it's not needed for you to do the build. If the docker registry is accessible you should first stop the running containers and then start them again.

    If you operate on swarm, it should be easier since swarm will check if containers have newer image base and will stop them only if image update is required.