Tam's Blog

<- Quay về trang chủ

Docker expose and publish command

Yesterday, I got stuck when trying to write a docker compose file of several services including redis, mysql and web services. The log of all web services showed that they couldn't connect to mysql database, after trying debugging and reading documentation, I've found that I misunderstood the usage of expose and publish command in dockerfile and docker-compose file. So I write this post to explain how expose and publish command work.

Docker network

In the scope of this post, I would only mention docker bridge network mode. Let's cite the definition from oficial documentation first:

A bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other.

In the above definition, you could easily see the function of this network driver: allows containers connected to the same bridge network to communicate, so basically you can commiunicate with others container through container name and port. This driver is the default one when you don't specify the driver of container.

    $ docker network ls --filter "name=bridge"
    NETWORK ID     NAME      DRIVER    SCOPE
    4064fdbdf055   bridge    bridge    local

Expose

The expose is just an instruction from the author of dockerfile for whom intends to use the image built from the dockerfile, it doens't actually publish the port of container.

Publish

Firstly, please see the below image for docker network.

If we don't public ports, we cannot access the container through the outside, like typing https://127.0.0.1/path in search bar of web browser of host machine. We could do this through -p option when running docker, or through port mapping of docker compose.

Example:

    $ docker run -p 5000:3000 --name signalling --rm signalling:1.0
    signal_server_1: &signal_server_1
    container_name: signal_server_1
    build:
     context: ./../signalling
    ports:
      - "5000:3000"
    restart: always
    depends_on:
      - matchmaker
      - redis

Behind the scenes, docker do all the things for us like creating the necessary Linux bridges, virtual network interface, ip table rules, routing,...

Now, you can access the container through port 5000, but do you see the difference of boundary in the above image?

Port 5000 is the mapping between the host manchine and docker, could I use this port to connect web container from database container? The answer is no, we cannot do something like

    curl https://web_container:5000

from inside the database container. This is also the thing I want to focus in this post. We can only access the web container through port 3000 because these two container are in the same network.

Tags: docker