feerlay
feerlay

Reputation: 2638

docker compose override a ports property instead of merging it

My docker compose configs look like this:

docker-compose.yml

version: '3.5'

services:
    nginx:
        ports:
            - 8080:8080

docker-compose.prod.yml

version: '3.5'

services:
    nginx:
        ports:
            - 80:80

Now, when I run command: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up the nginx exposes on host machine two ports: 8000 and 80, because it merges ports properties:

version: '3.5'

services:
    nginx:
        ports:
            - 8080:8080
            - 80:80

Is there a way to override it? I want to expose only port 80.

Upvotes: 90

Views: 34278

Answers (7)

sotmlac
sotmlac

Reputation: 194

I am adding this info maybe it will be helpful for somebody like me. I wanted to remove the ports that were set in docker-compose.yml by setting in the docker-compose.override.yml this:

version: '3.5'
services:
  nginx:
    ports: !reset []

As described in this article.

Upvotes: 6

Basit Ali
Basit Ali

Reputation: 949

This is now possible through docker-compose.override.yml file using the !override modifier.

services:
  nginx:
    ports: !override
      - "80:80"

Source: https://docs.docker.com/compose/compose-file/13-merge/#replace-value

Upvotes: 33

Zaffer
Zaffer

Reputation: 1809

Just keep the docker-compose.yml super simple and add the ports in another file docker-compose.develop.yml, then run it like docker-compose -f docker-compose.yml -f docker-compose.develop.yml up. This way you can separate it from your docker-compose.override.yml file.

So you will have three files:

|- docker-compose.yml # no ports specified
|- docker-compose.override.yml # ports 8080:8080
|- docker-compose.develop.yml #ports 80:80

Refer to this post for longer explanation: https://mindbyte.nl/2018/04/04/overwrite-ports-in-docker-compose.html

Upvotes: 7

Nikson Kanti Paul
Nikson Kanti Paul

Reputation: 3440

Use .override.yml file for overriding properties and a clear separation of properties need to be overridden

docker-compose.override.yml

Example:

version: '3.5'

services:
    nginx:
        ports:
            - 80:80

Default:

docker-compose up

will use your docker-compose.yml and docker-compose.override.yml files

Reference: docker-compose multiple compose

Upvotes: -6

Rach Sharp
Rach Sharp

Reputation: 2434

This behaviour is documented at https://docs.docker.com/compose/extends/#adding-and-overriding-configuration

For the multi-value options ports, expose, external_links, dns, dns_search, and tmpfs, Compose concatenates both sets of values

Since the ports will be the concatenation of the ports in all your compose files, I would suggest creating a new docker-compose.dev.yml file which contains your development port mappings, removing them from the base docker-compose.yml file.

As Nikson says, you can name this docker-compose.override.yml to apply your development configuration automatically without chaining the docker-compose files. docker-compose.override.yml will not be applied if you manually specify another override file (e.g. docker-compose -f docker-compose.yml -f docker-compose.prod.yml)

Upvotes: 59

Fl_ori4n
Fl_ori4n

Reputation: 360

it isn't possible a the moment but I found quite good way to fix this issue using the command yq. You need to remove the ports from the original file.

Example:
Be careful this command will remove the nginx ports from your current docker-compose.yml (because of the -i option)

yq e -i 'del(.services.nginx.ports)' docker-compose.yml

You can execute this command on your deployment script or manually before your docker-compose up -d

There's also an open issue on docker-compose, that you may want to check once in a while.

Upvotes: 4

zinovyev
zinovyev

Reputation: 2163

I've faced the same problem. The proposed solution with docker-compose.override.yml sounds pretty well and is also an official one.

Although for some of my own projects I've applied the erb template engine to make docker-compose.yml.erb file compile for multiple environments. In short I use:

COMPOSE_TEMPLATE_ENV=production erb docker-compose.yml.erb > docker-compose.yml
COMPOSE_TEMPLATE_ENV=production erb docker-compose.yml.erb > docker-compose-production.yml

And then I can use the ENV['COMPOSE_TEMPLATE_ENV'] in my template and also the syntax of ERB, so only one file to configure and no worries about piplening them properly. Here's the short post article I've written about it

Upvotes: 0

Related Questions