i thought i saw it on DO180 class also googled. I will take it next year.
Let’s consider a situation where we forgot to do the port mapping when starting the Docker container. There would be no way to access the service from a TCP/IP connection on the host.
There are three ways to deal with this:
Let’s dive deep into each of these solutions.
This is a naive solution where we remove the running Docker container and relaunch it using the same Docker image. But this time, we add the port mappings that we forgot to add in the old container.
This is the simplest and most straightforward approach, but it doesn’t suit all situations.
Consider a case where we launch the Docker container (without any port mapping) and perform some operations inside it, such as installing a few packages, launching processes, updating files and so on.
After all these changes, we realize that the port mapping is missing. Now if we launch a new Docker container using the same old Docker image, we’ll lose all those changes.
The next approach comes to the rescue under these circumstances.
However, we should note that it’s a good practice to use Docker volumes for our important data to make it easy to replace containers.
Instead of launching a new container from zero, we can commit the old Docker container to create a new Docker image and use that to start a new container with the right ports open.
Since we’re committing the old Docker container, the persistent state of the first will be available in the newly launched one.
Let’s try this out.
First, we’ll stop our Docker container and create its image using the docker commit command:
$ docker stop httpd-container httpd-container $ docker commit httpd-container httpd-image sha256:33da33fcad051c90ac9b7dea9b2dbda442767e05ddebd8d6db8ac6893ef4ef40
Next, we’ll remove the container and start a fresh container using the image that we just created.
We need to make sure we add/update the port mappings in the run command this time:
$ docker rm httpd-container
httpd-container
$ docker run -d -p 83:80 --name httpd-container httpd-image
dd2535c477ad74e80b3642abca9055efacb89eaf14572b91f91bf20cd3f0cbf3
Now we have a new container with the right port mappings to pick up where the previous one left off.
In the two approaches we’ve discussed so far, we removed the existing Docker container and started up a new one. Although the container works the same way, its metadata is completely different from the previous one.
Let’s now look at how to modify the existing Docker container instead.
First, let’s run a new Docker container without any port mapping:
$ docker run -d --name httpd-container httpd
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a0ed1c9fc60c httpd "httpd-foreground" 1 second ago Up 1 second 80/tcp httpd-container
The docker run command returns the full docker container ID, which is 64 characters in length.
Alternatively, this ID can also be found using the docker inspect command:
$ docker inspect --format="{{.Id}}" httpd-container
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
We’ll use the ID later to find the Docker configuration file path.
The first step of reconfiguring the running container is to stop it.
This can be done using the docker stop command:
$ docker stop httpd-container httpd-container
Since we’ll be updating the config files of the Docker container, we also need to stop the Docker service itself.
We should note that this will take all Docker containers down until we’re finished:
$ systemctl stop docker
All the config files related to Docker containers, images, volumes and networks can be found inside the /var/lib/docker directory. This directory will differ in the case of Windows and macOS.
We will focus mainly on two Docker container config files — hostconfig.json and config.v2.json.
These files are present inside this directory:
/var/lib/docker/containers/<ID>/
Here ID denotes the complete Docker container ID that we computed at the beginning of Section 6.
This is what its value came out to be:
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
So, in our case, the config files are present inside this directory:
$ ls /var/lib/docker/containers/a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7/
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7-json.log checkpoints config.v2.json hostconfig.json hostname hosts mounts resolv.conf resolv.conf.hash
Let’s first update the hostconfig.json file. We need to search for the PortBindings key in this JSON file. This field contains all the port mappings for that particular container.
Since we didn’t add any port mappings while running the Docker container, the PortBindings key will be empty for the httpd-container:
{
...
...
"PortBindings": {},
...
...
}
Let’s now assign host port 82 to port 80 of the Docker container httpd-container by updating the PortBindings in the JSON file:
{ ... ... "PortBindings": {"80/tcp":[{"HostIp":"","HostPort":"82"}]}, ... ... }
Once the port is mapped, we need to expose port 80 of the Docker container in the config.v2.json file.
We should add the ExposedPorts field (if not already present) inside the Config key:
{ ... "Config": { ... "ExposedPorts": { "80/tcp":{} }, ... } }
By doing so, we inform the Docker daemon that the container is listening on port 80 within that network interface.
Multiple ports can be exposed by passing the values as comma-separated key-value pairs:
{ ... "Config": { ... "ExposedPorts": { "80/tcp":{}, "82/tcp":{}, "8080/tcp":{} }, ... } }
It’s time to verify the changes that we’ve made so far.
First, let’s start the Docker service:
$ systemctl start docker
Now let’s start the docker container httpd-container and verify the port mapping using the docker ps command:
$ docker start httpd-container httpd-container root@ip-172-31-40-187:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a0ed1c9fc60c httpd "httpd-foreground" 1 hours ago Up 1 seconds 0.0.0.0:82->80/tcp, :::82->80/tcp httpd-container
Here we can see that the port mapping has been updated.
We can now access the httpd service from outside the Docker environment using port 82:
$ curl http://localhost:82 <html><body><h1>It works!</h1></body></html>
In this approach, the container id and other container-related metadata are preserved since we are not replacing the original Docker container.
We can also modify existing port mappings of any Docker container using the same procedure.
The only difference is that the PortBindings key in the hostconfig.json file will not be empty. We just need to update which port numbers we’re using.
If we update the Docker container TCP port in the port mapping, we also need to expose the same port inside the config.v2.json file.
Finally, we start the Docker service and the Docker container to bring the changes into effect.
In this article, we learned three different approaches for starting containers with the port mappings we need.
The first two approaches remove an existing Docker container and spin up a replacement.
Finally, we saw how to change the port mapping in an existing container by updating various Docker system config files while the Docker service was stopped.
If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.
Comments are closed on this article!;; that is googling
The podman option is publish (it's a bit like port forwarding):
-p <host_port>:<container_port>
Like:
podman run -d --name=<container_name> -p <host_port>:<container_port> <image>
For example:
$ podman run -d --name=web_server -p 8080:8080 rhcsl/httpd-24-rhel7
The container needs to listening on the <container_port> you specify.
To verify:
$ podman port <container_name>
Hello Tracy! But this solution I think that not fit to my question bc is when a container is already deployed, so if you already install many stuff on it and you forgot that you dont put the port mapping.
The normal thing would be to delete the container and launch a new one and reinstall everything again...
But docker has the peculiarity that you can stop de container, edit the configuration file and relaunch it without having to delete the container, but I have not been able to implement that solution in podman.
Anyway thanks for your help.
It sounds your container is doing too many things in manual ways. Why is it so costly to restart it?
The approach would be to build a static container with a Containerfile/Dockerfile, and restarting it should be pretty painless. Restarting could/shold be done via a script or systemd unit to ensure nobody forgets a required port.
Instead of installing software on a running container, try modifying the containerfile and building that into the image. Things that need to change frequently (database names, passwords, etc.) can be baked in as enviroment variables passed at container startup.
i thought i saw it on DO180 class also googled. I will take it next year.
Let’s consider a situation where we forgot to do the port mapping when starting the Docker container. There would be no way to access the service from a TCP/IP connection on the host.
There are three ways to deal with this:
Let’s dive deep into each of these solutions.
This is a naive solution where we remove the running Docker container and relaunch it using the same Docker image. But this time, we add the port mappings that we forgot to add in the old container.
This is the simplest and most straightforward approach, but it doesn’t suit all situations.
Consider a case where we launch the Docker container (without any port mapping) and perform some operations inside it, such as installing a few packages, launching processes, updating files and so on.
After all these changes, we realize that the port mapping is missing. Now if we launch a new Docker container using the same old Docker image, we’ll lose all those changes.
The next approach comes to the rescue under these circumstances.
However, we should note that it’s a good practice to use Docker volumes for our important data to make it easy to replace containers.
Instead of launching a new container from zero, we can commit the old Docker container to create a new Docker image and use that to start a new container with the right ports open.
Since we’re committing the old Docker container, the persistent state of the first will be available in the newly launched one.
Let’s try this out.
First, we’ll stop our Docker container and create its image using the docker commit command:
$ docker stop httpd-container httpd-container $ docker commit httpd-container httpd-image sha256:33da33fcad051c90ac9b7dea9b2dbda442767e05ddebd8d6db8ac6893ef4ef40
Next, we’ll remove the container and start a fresh container using the image that we just created.
We need to make sure we add/update the port mappings in the run command this time:
$ docker rm httpd-container
httpd-container
$ docker run -d -p 83:80 --name httpd-container httpd-image
dd2535c477ad74e80b3642abca9055efacb89eaf14572b91f91bf20cd3f0cbf3
Now we have a new container with the right port mappings to pick up where the previous one left off.
In the two approaches we’ve discussed so far, we removed the existing Docker container and started up a new one. Although the container works the same way, its metadata is completely different from the previous one.
Let’s now look at how to modify the existing Docker container instead.
First, let’s run a new Docker container without any port mapping:
$ docker run -d --name httpd-container httpd
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a0ed1c9fc60c httpd "httpd-foreground" 1 second ago Up 1 second 80/tcp httpd-container
The docker run command returns the full docker container ID, which is 64 characters in length.
Alternatively, this ID can also be found using the docker inspect command:
$ docker inspect --format="{{.Id}}" httpd-container
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
We’ll use the ID later to find the Docker configuration file path.
The first step of reconfiguring the running container is to stop it.
This can be done using the docker stop command:
$ docker stop httpd-container httpd-container
Since we’ll be updating the config files of the Docker container, we also need to stop the Docker service itself.
We should note that this will take all Docker containers down until we’re finished:
$ systemctl stop docker
All the config files related to Docker containers, images, volumes and networks can be found inside the /var/lib/docker directory. This directory will differ in the case of Windows and macOS.
We will focus mainly on two Docker container config files — hostconfig.json and config.v2.json.
These files are present inside this directory:
/var/lib/docker/containers/<ID>/
Here ID denotes the complete Docker container ID that we computed at the beginning of Section 6.
This is what its value came out to be:
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7
So, in our case, the config files are present inside this directory:
$ ls /var/lib/docker/containers/a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7/
a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7-json.log checkpoints config.v2.json hostconfig.json hostname hosts mounts resolv.conf resolv.conf.hash
Let’s first update the hostconfig.json file. We need to search for the PortBindings key in this JSON file. This field contains all the port mappings for that particular container.
Since we didn’t add any port mappings while running the Docker container, the PortBindings key will be empty for the httpd-container:
{
...
...
"PortBindings": {},
...
...
}
Let’s now assign host port 82 to port 80 of the Docker container httpd-container by updating the PortBindings in the JSON file:
{ ... ... "PortBindings": {"80/tcp":[{"HostIp":"","HostPort":"82"}]}, ... ... }
Once the port is mapped, we need to expose port 80 of the Docker container in the config.v2.json file.
We should add the ExposedPorts field (if not already present) inside the Config key:
{ ... "Config": { ... "ExposedPorts": { "80/tcp":{} }, ... } }
By doing so, we inform the Docker daemon that the container is listening on port 80 within that network interface.
Multiple ports can be exposed by passing the values as comma-separated key-value pairs:
{ ... "Config": { ... "ExposedPorts": { "80/tcp":{}, "82/tcp":{}, "8080/tcp":{} }, ... } }
It’s time to verify the changes that we’ve made so far.
First, let’s start the Docker service:
$ systemctl start docker
Now let’s start the docker container httpd-container and verify the port mapping using the docker ps command:
$ docker start httpd-container httpd-container root@ip-172-31-40-187:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a0ed1c9fc60c httpd "httpd-foreground" 1 hours ago Up 1 seconds 0.0.0.0:82->80/tcp, :::82->80/tcp httpd-container
Here we can see that the port mapping has been updated.
We can now access the httpd service from outside the Docker environment using port 82:
$ curl http://localhost:82 <html><body><h1>It works!</h1></body></html>
In this approach, the container id and other container-related metadata are preserved since we are not replacing the original Docker container.
We can also modify existing port mappings of any Docker container using the same procedure.
The only difference is that the PortBindings key in the hostconfig.json file will not be empty. We just need to update which port numbers we’re using.
If we update the Docker container TCP port in the port mapping, we also need to expose the same port inside the config.v2.json file.
Finally, we start the Docker service and the Docker container to bring the changes into effect.
In this article, we learned three different approaches for starting containers with the port mappings we need.
The first two approaches remove an existing Docker container and spin up a replacement.
Finally, we saw how to change the port mapping in an existing container by updating various Docker system config files while the Docker service was stopped.
If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.
Comments are closed on this article!;; that is googling
Hello Carey, but this method of editing the configuration file dont work in Podman. I already tried it and didn't work.
Anyway thanks for your help.
I would imagin it to be similar to port forwarding:
"-p 8080:80/tcp docker.io/library/httpd"
To add... i guess you could also:
Create a "container".service, then you can stop it with sudo systemctl stop "container".service
edit the config on container then sudo systemctl start "container".service
notes on making service...
vim /etc/systemd/system/container.service
[Unit] Description=container Podman 'container name'
Wants=syslog.service
[Service]
Restart=always
ExecStart=/usr/bin/podman start -a 'container name'
ExecStop=/usr/bin/podman stop -t 10 'container name'
[Install]
WantedBy=multi-user.target
Simply use -p option with the host port first 8080(host):80(container)
Red Hat
Learning Community
A collaborative learning environment, enabling open source skill development.