Docker Service与Docker run的端口映射差异解析
Hey there, let’s break down the port mapping differences between regular Docker containers and Docker Swarm services, especially focusing on that port conflict issue you mentioned with your Nginx container.
When you run a standalone container like this:
docker run -p 8091:80 --name container1 --net my-overlay-a nginx
You’re explicitly mapping host port 8091 to the container’s port 80. This locks that host port to container1—if you try to run another container (even accidentally reusing the same port mapping) with -p 8091:80, Docker will throw an error because the host’s 8091 port is already in use.
This works fine for single-instance workloads, but becomes a hassle if you want to run multiple copies of the same service on the same host—you’d have to manually assign unique host ports each time, which is tedious and error-prone.
Once you’ve initialized a Swarm with docker swarm init, services handle port mapping in ways that avoid these conflicts by default (or give you flexible, scalable options). Let’s cover the key scenarios:
1. Fixed Host Port (Single Instance Only)
If you use a fixed port mapping like:
docker service create --name nginx-service -p 8091:80 nginx
This behaves similarly to a standalone container on a single-node Swarm—the host’s 8091 port is bound to one service task (container). However, if you try to scale this service to multiple replicas (docker service scale nginx-service=3), Swarm will fail to start extra tasks on the same node because 8091 is already taken. Fixed ports are only practical for single-replica services in Swarm.
2. Random Host Ports (Multi-Replica Friendly)
If you omit the host port and only specify the container port:
docker service create --name nginx-service -p 80 nginx
Swarm will automatically assign a random host port (from the default range 30000-32767) to each service task. This means you can scale to as many replicas as your host can handle without port conflicts—each instance gets its own unique host port. You can check the assigned ports with docker service ps nginx-service or docker service inspect nginx-service.
3. Ingress Routing Mesh (Cluster-Wide Entry Point)
The most powerful option for Swarm is using the ingress publish mode, which creates a cluster-wide entry point for your service:
docker service create --name nginx-cluster --replicas 3 -p 80:80/tcp --publish-mode ingress nginx
Here’s how it works:
- Every node in the Swarm listens on host port 80.
- When traffic hits any node’s port 80, Swarm’s routing mesh automatically forwards it to one of the service’s tasks (regardless of which node the task is running on).
- You don’t have to worry about port conflicts because individual tasks don’t bind directly to the host’s 80 port—they communicate via Swarm’s internal overlay network.
- This also gives you built-in load balancing across replicas.
- For single-instance, host-bound workloads: Regular containers with fixed ports work fine, but you’ll hit conflicts if you try to run duplicates.
- For scalable, cluster-aware workloads: Use Docker Swarm services with either random ports (for direct task access) or the ingress routing mesh (for a unified, load-balanced entry point) to avoid port conflicts entirely.
内容的提问来源于stack exchange,提问作者dotnetstep

