Carlos.V
Carlos.V

Reputation: 446

Docker-compose multiple ports expose

My question is about expose multiple ports in one line from an ENV variable example, and these ports are not sequential, the same ports from host are going to be the same on container.

PORTS=80
PORTS=80,443
PORTS=80 443

And expose them in docker-compose.

according to docs, you can do.

ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"
 - "6060:6060/udp"

But i would like to do it another variable way

ports:
  - ${PORTS}:${PORTS}
#Sometimes this will be 
ports:
  - 80:80

#Other times this will be
ports:
  - 80,443:80,443 # Is this possible?
ports:
  - 80-443:80-443 # Don't want this because will export all the ports between
ports:
  - 80 443:80 443 # I think this is wrong syntax

Any clue or any other idea?

Upvotes: 1

Views: 11395

Answers (1)

DazWilkin
DazWilkin

Reputation: 40051

IIUC you cannot specify the ports mapping dynamically.

The Docker Compose YAML file is mostly a static configuration.

One way to address your problem is to generate the (ports section) YAML file.

You could and use a tool like sed to replace a variable in your Compose file with some generated output.

Suppose you have docker-compose.yaml:

  service:
    ...
    {{PORTS}}

Then

# List of ports to create
PORTS="80 443 8888"

# Generates "80:80""443:443""8888:8888" NB no commas between items
PORTS=$(for PORT in ${PORTS}; do printf '"%s:%s"' ${PORT} ${PORT}; done)

# Separate items with commas
PORTS=$(echo ${PORTS} | sed 's|""|","|g')

# Finalize the syntax for ports
PORTS="ports: [${PORTS}]"

# Replace {{TEMPLATE}} with the result
sed "s|{{PORTS}}|${PORTS}|g" docker-compose.yaml > docker-compose.new.yaml

Would yield docker-compose.new.yaml:

  service:
    ...
    ports: ["80:80","443:443","8888:8888"]

It's not very elegant but it should suffice.

NB I'm generating the ports as JSON for convenience (to avoid problems with newlines). YAML is a superset of JSON so you can use JSON instead of YAML for Docker Compose files.

Google (my employer) has a very nice tool for generating JSON (!) using a JSON-based templating language: Jsonnet. Because YAML is a superset of JSON, you may use JSON instead of YAML in your Docker Compose files.

Jsonnet:

local ports = ["80", "443", "8888"]; 
{"service":{
    "ports": [
        port + ":" + port
        for port in ports
    ]
}}

Generates:

{
  "service": {
    "ports": [
      "80:80",
      "443:443",
      "8888:8888"
    ]
  }
}

Upvotes: 3

Related Questions