Home > Software design >  Expose docker port based on environment variable in compose
Expose docker port based on environment variable in compose

Time:05-09

I am using docker compose to set up application environments. There are two distinct environments, test and production.

In a test environment, I need to expose additional ports (for debugging). These ports should remain closed in a production environment.

I would also like to use the same image and docker-compose.yml file. Using the same image is no problem but I am struggeling with the compose file. In it, I would like to open or close a port based on an environment variable.

The current setup is pretty much the standard, like this:

# ...
  ports:
    - "8080:8080" # HTTP Server port
    - "9301:9301" # debug port
# ...

In this example, both ports are always exposed. Is it possible to expose the port 9301 only if a certain environment variable, say EXPOSE_DEBUG, is set?

CodePudding user response:

You can use profiles or a second compose file.

services:
  app-prod:
    &app
    image: busybox
    profiles:
      - production
    ports:
      - 8080:8080

  app-dev:
    <<: *app
    profiles:
      - development
    ports:
      - 8080:8080
      - 9090:9090

Then you can use the below command or an environment variable to set the profile, COMPOSE_PROFILES.

docker compose --profile <profile-name> up

Alternatively, you can use a second compose file and override the ports.

# compose.yaml
services:
  app:
    image: busybox
    ports:
      - 8080:8080
# compose.dev.yaml
services:
  app:
    ports:
      - 8080:8080
      - 9090:9090

Then you can use the file after the main file to patch it:

docker compose -f compose.yaml -f compose.dev.yaml up

The file(s) to use can also be controls with an environment variable, COMPOSE_FILE.

If you name the file compose.override.yaml, docker will automatically use it, so you don't have to point to it with the -f flag. Be careful that you don't add this file to your production system, if you choose to do this.


You could also bind the debug port to the loopback interface so that you can only access it locally.

ports:
  - 8080:8080 
  - 127:0.0.1:9090:9090 

CodePudding user response:

The solution I usually use in my projects is to make a bash script that writes the docker-compose.yml based on the value of the environment variable. But you could write it with any other programming language as well.

CodePudding user response:

Conditional statements (if else) are not supported in docker compose.

  1. Use additional software like jinja-compose adding Jinja2 logic to docker-compose
  2. Use just two different files (dc-dev.yml and dc-prod.yml) and give them as arg (docker compose -f)
  3. Generate docker-compose.yml programmatically by yourself
  4. Use profiles (Was to slow, see answer of the fool)

To just maintain dev/prod environments in my opinion solution 2 is the most efficient in terms of effort.

To follow your approach:

You can set port mapping by envs like:

.env-File or add them in docker compose up -e command

PORT1="8080:8080"
PORT2="9301:9301"

docker-compse.yml

services:
  container1:
    ports:
      - ${PORT1}
      - ${PORT2}

But afaik there is no way to omit one of them

  • Related