Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I avoid 'port collision' when using docker?

Tags:

docker

mysql

port

I hope the title is descriptive enough. I am trying to execute my node app (that uses mongo and mysql) in docker. I am using docker-compose to start the app and docker-compose.yml file below:

version: "3.3"
services:
  app:
    container_name: app
    restart: always
    build: .
    volumes:
      - ./:/app
    ports:
      - "3000:3000"
    links:
      - mongo
      - mysql
  mongo:
    container_name: mongo
    image: mongo
   ports:
      - "27017:27017"
  mysql:
    container_name: mysql
    image: mysql
    ports:
      - "3306:3306"

Whenever I try to start this using docker-compose up I get the following error:

ERROR: for mysql  Cannot start service mysql: driver failed programming external connectivity on endpoint mysql (785b03daaa662bb3c344025f89fd28f49eabb43104b1c9a16ab425ab5120309f): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use

ERROR: for mysql  Cannot start service mysql: driver failed programming external connectivity on endpoint mysql (785b03daaa662bb3c344025f89fd28f49eabb43104b1c9a16ab425ab5120309f): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.

I did a little bit of research and it seems that gitlab-runner is using the mysql service. My understand was that if I run this setup through docker container they are isolated from the host system so I won't have any port conflicts. The only ports that I am exposing are the ones in my Dockerfile - in my case 3000. Am I missing something in my docker-compose.yml? What else could be wrong?

like image 270
Crosswind Avatar asked Jan 16 '18 13:01

Crosswind


People also ask

Does Docker automatically expose port?

By default, when you create or run a container using docker create or docker run , it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container's network, use the --publish or -p flag.

Can two Docker containers expose same port?

Surprisingly or not, neither Docker nor Podman support exposing multiple containers on the same host's port right out of the box. Example: docker-compose failing scenario with "Service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash."

What port should I use for Docker?

When you open the browser and navigate to the Docker host on port 8080, you will see Jenkins up and running.

Does Docker bypass firewall?

Docker Network bypasses Firewall, no option to disable Check the firewall; docker will by use "anywhere" as the source, thereby all containers are exposed to the public.


1 Answers

Stop binding to local ports and let docker-compose pick an ephemeral port for you. In your case, your application can get to the default ports without any help. If you are following the 12 Factor App approach, then use environment variables like in the following snippet.

version: "3.3"
services:
  app:
    restart: always
    build: .
    volumes:
      - ./:/app
    ports:
      - 3000  # will be bound to an ephemeral port
    environment:
      MONGODB_URL: mongodb://mongo/db  # can reach port 27017 without help
  mongo:
    image: mongo
    ports:
      - 27017

This is the primary reason to make your applications configurable via environment variables or command-line flags.

You can use docker-compose port to get the ephemeral port if you need to access a docker application from the host. I routinely use a shell function like the following:

get_exposed_port() {  # SERVICE PORT
    docker-compose port $1 $2 | cut -d: -f2
}
like image 113
D.Shawley Avatar answered Oct 14 '22 00:10

D.Shawley