Pushing Docker images to a private registry with Docker Compose

May 18, 2019  •  3 min read

Recently I was looking for a way to push services’ images of a Docker Compose project to a private registry. In this article I’m going to save you some guesswork as the process is a bit ambiguous.

Before we go any further let’s first set up the stage. We have a simple docker-compose.yml file with the following contents:

version: '3'

services:
  myapp:
    build: ./services/myapp

I want to build the image and push it to my private Docker registry.

docker-compose build

So far so good. Everything builds well. I decide to check my local images:

docker images

And the first issue I notice is the bad naming of my image: “myprojectname_myapp latest”

Easy fix — if you specify image as well as build configuration options, docker-compose will build the image with the specified image name and tag, as described in the docs:

version: '3'

services:
  myapp:
    image: myproject/myapp:latest
    build: ./services/myapp

Now my image has appropriate naming and I want to push it. With the current setup, however, docker-compose push will try to push the project’s images to the Docker Hub registry. I don’t want this to happen.

At first glance the compose file reference doesn’t provide neither configuration nor information on how to push images to a private registry.

If you want to push an image to a private registry you need to follow those instructions:\

1. docker tag myproject/myapp:latest my-registry-host:5000/myproject/myapp:latest\

2. docker push my-registry-host:5000/myproject/myapp:latest

There are some guides on the Internet suggesting automating those steps with a script but I don’t like this solution as I want to use the native tooling. A few minutes later I arrived at the docker-compose push documentation page which includes a nice example.

It looks like the image service configuration option follows the same notation as the example above:

version: '3'

services:
  myapp:
    image: my-registry-host:5000/myproject/myapp:latest
    build: ./services/myapp

Now when I execute docker-compose push my image gets pushed to my private image registry. There is something that still annoys me though — if I decide to change the registry, I need to edit the image configuration option of all described services.

For this reason I like to extract the registry host as an environment variable:

REGISTRY_HOST=my-registry-host:5000
version: '3'

services:
  myapp:
    image: ${REGISTRY_HOST}/myproject/myapp:latest
    build: ./services/myapp

Congratulations! Now you will be able to build and distribute your project’s images by only using the native tooling provided by Docker and Docker Compose.