How Docker Port Mapping works - External Ports

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
When starting a docker-compose.yml by default the containers are isolated in an 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
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 port80
- App B HTTP port is
38082
, internal apache port80
- App C HTTP port is
48082
, internal apache port80
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
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.
Get quality content updates subscribing to the newsletter, Zero Spam!