skip to Main Content

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?

3

Answers


  1. 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.

    Login or Signup to reply.
  2. 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 
    
    Login or Signup to reply.
  3. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search