Wax Cage
Wax Cage

Reputation: 788

How to make docker-compose build image once and repeatedly use it to run containers?

I am trying to run multiple containers built from the same image. My problem is when I define my docker-compose.yml this way

version: '3'
services:
    crossbar-target:
        container_name: "app-crossbar-target"
        build:
            context: ../../crossbar

    crossbar-source-domain1:
        container_name: "app-crossbar-source-domain1"
        build:
            context: ../../crossbar

    crossbar-source-domain2:
        container_name: "app-crossbar-source-domain2"
        build:
            context: ../../crossbar

I will get three containers as I want them, but I get three images as well.

In case I have hundreds of containers, I don't like the idea having hundreds of images as well. That makes my local image repository completely unusable and unreadable.

Thinking and searching for solution I tried define crossbar image by itself and then reuse it:

version: '3'
services:
    app-crossbar:
        build:
        context: ../../crossbar

    crossbar-target:
        container_name: "app-crossbar-target"
        image: project_name/app-crossbar

    crossbar-source-domain1:
        container_name: "app-crossbar-source-domain1"
        image: project_name/app-crossbar

    crossbar-source-domain2:
        container_name: "app-crossbar-source-domain2"
        image: project_name/app-crossbar

Now, I have only one image for all containers, but get an app-crossbar container as well. That doesn't suit my needs as well.

Is there any way to make docker-compose manage my images efficiently and make only those images I need and then use them to run containers in any amount needed? Or do I have to manage my images separately in some other routines? I like calling:

docker-compose build

to rebuild all needed images and I like the idea that all my docker logic is held in one place.

Upvotes: 8

Views: 13437

Answers (1)

Grimmy
Grimmy

Reputation: 4137

Build the crossbar image first and properly tag it. Then you can spawn multiple services using that image. The latest tag here is only an example. I would use a unique version number.

version: '3'
services:
    app-crossbar:
        image: crossbar:latest

    crossbar-target:
        image: crossbar:latest

    crossbar-source-domain1:
        image: crossbar:latest

    crossbar-source-domain2:
        image: crossbar:latest

A huge advantage of pre-building images (and possibly storing them in an docker image repo) is that you can revert to older versions when needed. In addition you can run tests with the pre-build images if needed.

It's pretty standard to have a CI setup where for example Jenkins builds a new image of your crossbar project (when you push a branch), properly tags it an pushes the image to your private (or public) image repo.

I'd say even if you could build the image with compose, that is still not the right way to do it for prod. It might be acceptable if you extend your image to add a layer with config files. By pre-building images your pipeline is also compatible with swarm and other clustered environments.

If this is overkill for your needs you just build locally (and TAG the images properly). The tagging part is important so you don't have to battle with docker cache and you can still find older versions if a revert is needed.

(In a dev environment you can be a more careless and just map in directories and file from the host to the containers. No one wants to re-build for every single change)

Upvotes: 9

Related Questions