Exposing a port on a live Docker container

2019-01-03 03:57发布

I'm trying to create a Docker container that acts like a full-on virtual machine. I know I can use the EXPOSE instruction inside a Dockerfile to expose a port, and I can use the -p flag with docker run to assign ports, but once a container is actually running, is there a command to open/map additional ports live?

For example, let's say I have a Docker container that is running sshd. Someone else using the container ssh's in and installs httpd. Is there a way to expose port 80 on the container and map it to port 8080 on the host, so that people can visit the web server running in the container, without restarting it?

标签: docker
14条回答
老娘就宠你
2楼-- · 2019-01-03 04:07

Read Ricardo's response first. This worked for me.

However, there exists a scenario where this won't work if the running container was kicked off using docker-compose. This is because docker-compose (I'm running docker 1.17) creates a new network. The way to address this scenario would be

docker network ls

Then append the following docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-03 04:09

IPtables hacks don't work, at least on Docker 1.4.1.

The best way would be to run another container with the exposed port and relay with socat. This is what I've done to (temporarily) connect to the database with SQLPlus:

docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus

Dockerfile:

FROM debian:7

RUN apt-get update && \
    apt-get -y install socat && \
    apt-get clean

USER nobody

CMD socat -ffffdd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521
查看更多
Ridiculous、
4楼-- · 2019-01-03 04:11

Here are some solutions:

https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12

The solution to mapping port while running the container.

docker run -d --net=host myvnc

that will expose and map the port automatically to your host

查看更多
再贱就再见
5楼-- · 2019-01-03 04:13

While you cannot expose a new port of an existing container, you can start a new container in the same Docker network and get it to forward traffic to the original container.

# docker run \
  --rm \
  -p $PORT:1234 \
  verb/socat \
    TCP-LISTEN:1234,fork \
    TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT

Worked Example

Launch a web-service that listens on port 80, but do not expose its internal port 80 (oops!):

# docker run -ti mkodockx/docker-pastebin   # Forgot to expose PORT 80!

Find its Docker network IP:

# docker inspect 63256f72142a | grep IPAddress
                    "IPAddress": "172.17.0.2",

Launch verb/socat with port 8080 exposed, and get it to forward TCP traffic to that IP's port 80:

# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80

You can now access pastebin on http://localhost:8080/, and your requests goes to socat:1234 which forwards it to pastebin:80, and the response travels the same path in reverse.

查看更多
走好不送
6楼-- · 2019-01-03 04:13

It's not possible to do live port mapping but there are multiple ways you can give a Docker container what amounts to a real interface like a virtual machine would have.

Macvlan Interfaces

Docker now includes a Macvlan network driver. This attaches a Docker network to a "real world" interface and allows you to assign that networks addresses directly to the container (like a virtual machines bridged mode).

docker network create \
    -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    -o parent=eth0 pub_net

pipework can also map a real interface into a container or setup a sub interface in older versions of Docker.

Routing IP's

If you have control of the network you can route additional networks to your Docker host for use in the containers.

Then you assign that network to the containers and setup your Docker host to route the packets via the docker network.

Shared host interface

The --net host option allows the host interface to be shared into a container but this is probably not a good setup for running multiple containers on the one host due to the shared nature.

查看更多
可以哭但决不认输i
7楼-- · 2019-01-03 04:14

In case no answer is working for someone - check if your target container is already running in docker network:

docker inspect my-target-container | grep NetworkMode
        "NetworkMode": "my-network-name",

If yes, you should run the proxy container in the same network.

docker inspect my-target-container | grep -A2 Aliases
                "Aliases": [
                    "my-alias",
                    "23ea4ea42e34a"

Final command:

docker run --net my-network-name --name my-new-proxy \
-d -p 8080:1234 alpine/socat TCP-LISTEN:1234,fork TCP-CONNECT:my-alias:80
查看更多
登录 后发表回答