Docker container with multiple configurable ports - docker

I have a container that runs a node app with three servers: one server for public data and two webpack servers. By default these run on ports 3000, 3001, and 3002, but these ports can all be configured.
It seems that I would be able to run the container like so:
docker run -p 3000:3003 -p 3001:3004 -p 3002:3005 -e 'APP_PORT=3003' \
-e 'NG_PORT=3004' -e 'RC_PORT=3005' --expose 3003 --expose 3004 --expose 3005 \
ajcrites/webf
However there are two problems with this approach:
There is a tremendous amount of redundancy
I want the default ports to be used/exposed if nothing is specified
Is there a simpler way to expose all of the configurable ports whether or not they are changed from the defaults?

You wouldn't want to expose ALL ports, however you can expose and bind by range since at least docker 1.5:
docker run -p 3000-3002:3003-3005
I don't think you need to use --expose when you publish.

Related

What is the interaction between docker run "--publish" and "--publish-all"?

I couldn't find this documented. Suppose I wanted to publish one port to a known place, but sometime publish all the other "exposed" ports for debugging or testing.
A simple Dockerfile
FROM alpine
CMD /bin/sleep 600
--publish/-p allows me to bind a specific host port to a container port. --publish-all/-P binds all container ports to random ports, which can be found using, for example docker ps.
$ docker build -t foo .
<build prints>
$ docker run -d -p 8000:8000 -P -p 9000:9000 foo
<some id prints>
$ docker ps --format '{{.Command}} {{.Ports}}'
"/bin/sh -c '/bin/sl…" 0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp
But suppose I have a Dockerfile like this, and publish one port to a known port but the rest to randomly assigned ports.
FROM alpine
EXPOSE 8000
# Various management ports or something
EXPOSE 8005
EXPOSE 8443
EXPOSE 8009
CMD /bin/sleep 600
What is the defined behavior for
$ docker run -d -P -p 8000:8000 foo
Doing exactly this the behavior seems to be "as expected". The explicit port bindings take precedence over the --publish-all, independent of where the flags occur. In the example above, the results are
$ docker ps --format '{{.Command}} {{.Ports}}'
"/bin/sh -c '/bin/sl…" 0.0.0.0:8000->8000/tcp, 0.0.0.0:32792->8005/tcp, 0.0.0.0:32791->8009/tcp, 0.0.0.0:32790->8443/tcp
The explicit requested port binding occurs, and the other ports are bound to os-assigned unused ports.
It also clarified something to me I did not understand. I've always mostly ignored "EXPOSE" since the documentation basically said that it doesn't actually do anything but serve as documentation, and to actually "expose" a port you should publish it explicitly. But --publish-all does use the exposed ports. I had been naively thinking that by doing --publish-all it would publish ALL the ports that the process I had started was listening on, but those ports are opened after the container is already initialized.

How to run two instances of a Service without binding to specific port

I have two problem Statement for running the docker container.
Run two instances of a docker container.
I am running a container say test-service. When I execute the command Only one container named as test-service get created. I want to change the command and create one more instance of the container.
Dynamic Port number Allocation to the container.
I am binding the port say 8080:8080. I want to configure it in such a way that the port number will be dynamic.
The command which I am using to run the container is as below:
docker run -p ${EXTERNAL_PORT_NUMBER}:${INTERNAL_PORT_NUMBER} --network ${NETWORK} --name ${SERVICE_NAME} --restart always -m 1024M --memory-swap -1 -itd ${ORGANISATION}/${SERVICE_NAME}:${VERSION}
The test-service is a node service.
Please let me know what modifications are needed in the above command.
For 2nd question:
Use --publish-all flag instead of providing port mapping.
$ docker run --publish-all --network ${NETWORK} --name ${SERVICE_NAME} --restart always -m 1024M --memory-swap -1 -itd ${ORGANISATION}/${SERVICE_NAME}:${VERSION}
This will publish a container's port(s) to the host port. Host port will be dynamic. And all container ports will be exposed.
But if you want to expose specific port, use -p :<port>
$ docker run -p :${INTERNAL_PORT_NUMBER} --network ${NETWORK} --name ${SERVICE_NAME} --restart always -m 1024M --memory-swap -1 -itd ${ORGANISATION}/${SERVICE_NAME}:${VERSION}
Leave ${EXTERNAL_PORT_NUMBER} part empty, then a port will be selected dynamically.
For 1st question:
You can use docker-compose. Check this answer.
Or, you can run docker run multiple time. In this case, use different --name

How to forward all ports in docker container

Consider:
docker run -p 5000:5000 -v /host/:/host appimage
it forwards 5000 to 50000
even in multiple:
docker run -p 5000:5000 -p 5001:5001 -v /host/:/host appimage
What I want to know is:
docker run -p allports:allports
is there any command available that allows to forward all ports in container? Because in my case I am running flask app. For testing purpose I want to run multiple flask instances. So for each flask instance I want to run it in different ports. This auto multi-port forwarding would help.
You can expose a range of ports using the -p option, for example:
docker run -p 2000-5000:2000-5000 -v /host/:/host appimage
See the docker run reference documentation for more details.
You might have a working set-up by using docker run --net host ..., in which case host's network is directly exposed to the continer and all port bindings are "public". I haven't tested this with multiple containers simultaneously but it might work just fine.

docker run with -p and a single port (instead of mapping)

What is the different between the following commands when creating a container in docker?
docker run -d -p 8080 sample/image
and
docker run -d -p 8080:8080 sample/image
I have seen majority of them use the second command, but I am not sure if they mean different things, or if the first is shorthand.
I couldn't find any material on this.
docker run -d -p 8080 sample/image
Exposes port 8080 of the container as an arbitrary port on the host. Which port that is is up to Docker.
Whereas,
docker run -d -p 8080:8080 sample/image
Exposes port 8080 of the container as port 8080 on the host.
In both cases, you can see the mapping using docker inspect, or even docker ps:
380af8c2bcc6 ubuntu "bash" 15 seconds ago Up 13 seconds 0.0.0.0:32768->1234/tcp elegant_meitner
In this case, port 1234 of the container is exposed as port 32768 on the host.

Ambiguous port publish parameters to "docker run"

Docker's shipyard project has a prebuilt container to simplify running its components. It's simply just a run script that launches and links several other containers.
However, I find their usage of the port-publish parameter (-p) confusing in two of the run commands:
sudo docker run -i -t -d -p 80 --link shipyard_redis:redis --name shipyard_router shipyard/router
sudo docker run -i -t -d -p 80:80 --link shipyard_redis:redis --link shipyard_router:app_router --name shipyard_lb shipyard/lb
The first command passes a single parameter to "-p", which doesn't seem legal, since every official usage is suppose to have at least two, colon-separated parts:
-p, --publish=[] Publish a container's port to the host
format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
(use 'docker port' to see the actual mapping)
The second command is confusing because it seems like this would cause a port collision with the container started in the first command.
Can someone clarify?
When you specify -p with only 1/single port number. Docker automatically assigns a random port mapping (usually starting from port 49150) to the single port exposed in the container ie. 80
what this means is, lets say you run Apache 2 on port 80 inside your container. Then you will have to point your browser to localhost:49150 to access your Apache web server.

Resources