The docker network is isolated from the outside by default, when we want to connect from outside to a docker container we use/create a port mapping and this get exposed through localhost, 127.0.0.1 or your IP address.

[!note] 127.0.0.1 is a loopback address that the system uses to communicate to itself, there is a DNS auto resolved name called localhost that points to 127.0.0.1.

In this example we are going to configure a Web Server and a MySQL database.

# Create a directory for your project.
mkdir port-mappings

# Create the docker-compose.yml file.
touch docker-compose.yml

# Access the created file using nano or your prefered editor.
nano docker-compose.yml

Inside the docker-compose.yml we are going to paste the following:

services:
	web:
	  image: nginx
	  ports:
	   - "28082:80"
	db:  
	    image: mysql:5.7  
	    restart: always  
	    environment:  
	      MYSQL_DATABASE: 'db'  
	      MYSQL_USER: 'user'  
	      MYSQL_PASSWORD: 'password'  
	      MYSQL_ROOT_PASSWORD: 'password'  
	    ports:
	      - '23306:3306'  

[!warning] As the database container doesn’t have a volume provided for persistance, the data will be flush everytime the server is restarted. We will cover Volumes on another post.

Now lets execute:

# Start the containers defined in the docker-compose.yml
docker-compose up -d

Access the web server Web server

Nginx Server

When starting a docker-compose.yml by default the containers are isolated in an internal network.

Docker Internal network

If we want to access the container from our machine we need to use a port mapping, in the docker-compose.yml we define the following:

  • “28082:80” for web server
    • http://localhost:28082
  • “23306:3306” for MySQL in
    • host:localhost
    • port:23306

Local network and port mapping

If we want to connect the Web Server with the MySQL server, we need to use the internal port (3306)

  • host:localhost
  • port:3306

By default MySQL uses 3306 port and the container is set like that, this is fine, but you might be running more than one mysql at the same time and using 3306 is not possible as this was already taken by the first started service, this is when we do the mapping, 13306, 23306 or 33067 works.

  • From outside the docker container (Local env), use the exposed port 23306 (or any other defined).
  • From inside use the 3306

Keep in mind that every docker-compose file created their own isolated network, this means that if you started App A and App B, they will not be able to connect, unless we create a network and map both projects with the same network (We will explain this in another post) 

Having isolated docker networks allow to have several projects with databases running on internal port 3306 without causing an error, running several web servers would look like this:

  • App A HTTP port is 28082, internal apache port 80
  • App B HTTP port is 38082, internal apache port 80
  • App C HTTP port is 48082, internal apache port 80
services:
	web:
	  image: nginx
	  ports:
	   - "28082:80"
	web2:
	  image: nginx
	  ports:
	   - "38082:80"
	web3:
	  image: nginx
	  ports:
	   - "48082:80"
# Start the containers defined in the docker-compose.yml
docker-compose up -d

Several apps running with different ports

Now lets do the same but for the MySQL server:

services:
	db:  
	    image: mysql:5.7  
	    restart: always  
	    environment:  
	      MYSQL_DATABASE: 'db'  
	      MYSQL_USER: 'user'  
	      MYSQL_PASSWORD: 'password'  
	      MYSQL_ROOT_PASSWORD: 'password'  
	    ports:
	      - '23306:3306'  
	db2:  
	    image: mysql:5.7  
	    restart: always  
	    environment:  
	      MYSQL_DATABASE: 'db'  
	      MYSQL_USER: 'user'  
	      MYSQL_PASSWORD: 'password'  
	      MYSQL_ROOT_PASSWORD: 'password'  
	    ports:
	      - '33306:3306'
	db3:  
	    image: mysql:5.7  
	    restart: always  
	    environment:  
	      MYSQL_DATABASE: 'db'  
	      MYSQL_USER: 'user'  
	      MYSQL_PASSWORD: 'password'  
	      MYSQL_ROOT_PASSWORD: 'password'  
	    ports:
	      - '43306:3306'

# Stop the containers
docker-compose down

I hope this helps to understand how port mapping works with docker.