I try to run 3 containers: nginx and two containers with flask-uwsgi but one for staging one for live.
In docker i create network:
docker network create --attachable --subnet 1.1.1.0/29 some-network
And run containers like:
# nginx
docker run -d --rm
--net some-network --ip 1.1.1.2
-p 80:80 -p 443:443
--name my-nginx "$REGISTRY/$IMAGE"
# flask+uwsgi on :8080 (live)
docker run -d --rm
--net some-network --ip 1.1.1.3
-p 8080:8080
--name flask-live "$REGISTRY/$IMAGE"
And i have default server config with upstreams:
upstream flask_live {
server 1.1.1.3:8080;
}
upstream flask_dev {
server 1.1.1.4:8080;
}
server {
listen 80;
server_name hostname.com;
location / {
include uwsgi_params;
uwsgi_pass flask_live;
}
}
server {
listen 80;
server_name develop.hostname.com;
location / {
include uwsgi_params;
uwsgi_pass flask_dev;
}
}
But when i try to run third container with flask develop like:
docker run -d --rm
--net some-network --ip 1.1.1.4
-p 8080:8080
--name flask-live "$REGISTRY/$IMAGE"
I get error: Bind for 0.0.0.0:8080 failed: port is already allocated
I don’t understand why port allocated if i try to publish on 1.1.1.0/29 subnet
I read docker docs about networking, I google stuff but I am just blind or slow but i don’t understand how to "isolate" container or something like that.
2
Answers
-p 8080:8080
is equal to-p 0.0.0.0:8080:8080
where:0.0.0.0
– address on the host to redirect from8080
– port to redirect from8080
– port of container (inside docker network)So, your error message says that you cannot bind to port 8080 of the host (not your internal docker network).
This command allows you to access your container from host network (eg. from
localhost:8080
to 8080 port of your container). Basically, it usesiptables
to redirect packets from one network to another. So, when you call-p 8080:8080
, it will redirect packets from port 8080 to your first container and when you call the same command for second container it fails, because port 8080 is already in use. You cannot you the single port to redirect to both containers at the same time.Based on your description, you don’t even need to publish ports to your flask-uwsgi containers, because you have a nginx proxy, which will allow you to access them based on host names. These ports will still be available inside your
Docker
network, you just won’t publish then to your host OS.If you still need to access your flask-uwsgi containers directly (without
nginx
), then you can publish them to different ports. Eg. first –-p 8081:8080
, second –-p 8082:8080
).The
docker run -p
option opens a port on the host that forwards to a port in the container. That generally means you can’t run two containers that have the same first-p
port number, and that first port number also can’t conflict with a non-container process running on the host.Separately, Docker maintains its own networking layer. It’s useful to know that, as an implementation detail, each container happens to have its own IP address, so you can run processes in separate containers that each listen on port 8080 and they won’t conflict. You don’t need a
-p
option to do this.So: connections from outside Docker…
docker run -p
port number (which must be unique across all containers and host processes)-p
port number and the special 0.0.0.0 "everywhere" IP addressConnections between containers…
docker run --net
networkdocker run --name
as a DNS namedocker run -p
port mappingsNotice that neither of these cases actually needs to know the container-private IP address, and it’s not usually useful to specify these or look them up. In your example I would delete the
docker network create --subnet
option and thedocker run --ip
options.