Create First docker-compose File

To create multiple containers we need to use docker-compose.yaml file, let’s understand how a docker-compose file works and what instructions need to be defined inside it.

To run a nginx container the manual is

gaurav@learning-ocean:~$ docker container run -itd nginx

but if the same container if we want to create using docker-compose file then we need to create a YAML file using vi docker-compose.yaml and snippet is shown below

version: "3"
services:
  webapp1:
    image: nginx
    ports:
      - "8000:80"

Version Property is defined by the specification for backward compatibility but is only informative.

Services It defines the number of applications or containers which need to be created. As shown in the above example under webapp1 it defines the first container which will get created using image nginx and expose ports “8000:80”. By giving the image name as nginx, we are specifying the container should get built on nginx and we can give any image name as per the requirement. Ports property defines the port mapping of the host to the container, port 8000 is the host port that will map to port 80 of the container.

After creating the docker-compose.yaml file, run docker-compose up -d and it will create a new container .

output:

gaurav@learning-ocean:~/docker-compose$ sudo docker-compose up -d
[sudo] password for gaurav:
Creating network "docker-compose_default" with the default driver
Pulling webapp1 (nginx:)...
latest: Pulling from library/nginx
a330b6cecb98: Already exists
e0ad2c0621bc: Pull complete
9e56c3e0e6b7: Pull complete
09f31c94adc6: Pull complete
32b26e9cdb83: Pull complete
20ab512bbb07: Pull complete
Digest: sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e
Status: Downloaded newer image for nginx:latest
Creating docker-compose_webapp1_1 ... done
gaurav@learning-ocean:~/docker-compose$ sudo docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                  NAMES
2939df15d408   nginx     "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:8000->80/tcp   docker-compose_webapp1_1
gaurav@learning-ocean:~/docker-compose$ sudo docker network ls
NETWORK ID     NAME                     DRIVER    SCOPE
0022a9f511fe   bridge                   bridge    local
b96ba06066a8   docker-compose_default   bridge    local
3a33f83c3663   host                     host      local
e4ebd601732c   none                     null      local

As shown in the above output ,new nginx container is up and the command also shows the mapping of ports along with the name of the container. Now the Nginx application could be accessed by giving localhost and port in URL as shown below.

docker-compose-create-first-docker-compose

Docker-compose command creates the new network and docker compose down will delete all the created configuration

output:

gaurav@learning-ocean:~/docker-compose$ docker-compose down
Stopping docker-compose_webapp1_1 ... done
Removing docker-compose_webapp1_1 ... done
Removing network docker-compose_default
gaurav@learning-ocean:~/docker-compose$ docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
gaurav@learning-ocean:~/docker-compose$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
0022a9f511fe   bridge    bridge    local
3a33f83c3663   host      host      local
e4ebd601732c   none      null      local

Now, suppose we want to create two containers using docker-compose YAML file. It's very easy ,just require one more webapp to be defined inside YAML file as shown below

version: "3"
services:
  webapp1:
    image: nginx
    ports:
      - "8000:80"
  webapp2:
    image: nginx
    ports:
      - "8001:80"

Webapp2 is the second container which will bring up the same image as nginx(can be changed as per your choice) and the host port has changed to 8001 and now as shown below webapp2 container is up on 8001 port of host.

docker-compose-create-first-docker-compose

output:

gaurav@learning-ocean:~/docker-compose$ docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_webapp2_1 ... done
Creating docker-compose_webapp1_1 ... done
gaurav@learning-ocean:~/docker-compose$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
4f4a2060650c   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 4 seconds   0.0.0.0:8001->80/tcp   docker-compose_webapp2_1
e7923ed200c0   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:8000->80/tcp   docker-compose_webapp1_1
gaurav@learning-ocean:~/docker-compose$ docker network ls
NETWORK ID     NAME                     DRIVER    SCOPE
0022a9f511fe   bridge                   bridge    local
a6a32f981f30   docker-compose_default   bridge    local
3a33f83c3663   host                     host      local
e4ebd601732c   none                     null      local
gaurav@learning-ocean:~/docker-compose$ docker volume ls
DRIVER    VOLUME NAME
gaurav@learning-ocean:~/docker-compose$

What happens if we re-run the docker-compose file, Will it recreates the same containers again? The answer to this question is, docker, compose will read the yaml file instruction and it will only recreate the container if it has any changes in any of the properties.

Let’s change the host port of webapp2 to 8002 and rerun the docker-compose command

output:

gaurav@learning-ocean:~/docker-compose$ cat docker-compose.yaml
version: '3'
services:
  webapp1:
    image: nginx
    ports:
      - "8000:80"
  webapp2:
    image: nginx
    ports:
      - "8002:80"
gaurav@learning-ocean:~/docker-compose$ docker-compose up -d
docker-compose_webapp1_1 is up-to-date
Recreating docker-compose_webapp2_1 ... done
gaurav@learning-ocean:~/docker-compose$

As shown in above output only webapp2 is getting re-created because the host port for it has been changed from 8001 o 8002

Docker-compose up command always search for docker-compose.yaml file in the present working directory and if you change this file name docker compose command will fail as shown below:

output:

gaurav@learning-ocean:~/docker-compose$ mv docker-compose.yaml docker-compose.yaml.bkp
gaurav@learning-ocean:~/docker-compose$ ls
docker-compose.yaml.bkp
gaurav@learning-ocean:~/docker-compose$ docker-compose up -d
ERROR:
        Can't find a suitable configuration file in this directory or any
        parent. Are you in the right directory?
        Supported filenames: docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml
gaurav@learning-ocean:~/docker-compose$

an we Change the docker-compose.yaml's file name?

There may be a situation in the future where user doesn’t want to give the default name of compose file due to various reasons, the user wants to give its own file name, this could also be achieved by using -f flag of docker compose command and by specifying -f option docker will not search for default file instead it will search for file provided after -f flag.

gaurav@learning-ocean:~/docker-compose$ docker-compose -f docker-compose.yaml.bkp up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_webapp1_1 ... done
Creating docker-compose_webapp2_1 ... done
gaurav@learning-ocean:~/docker-compose$

can we write a docker-compose file in JSON or any other format ?

Another important point to highlight is ,it is not mandatory to have only yaml file format for docker compose command, it can also work with JSON file format. Convert the yaml instruction to json and create a json file using vi docker-compose.json

{
  "version": "3",
  "services": {
    "webapp1": {
      "image": "nginx",
      "ports": ["8000:80"]
    },
    "webapp2": {
      "image": "nginx",
      "ports": ["8002:80"]
    }
  }
}

output:

gaurav@learning-ocean:~/docker-compose$ docker-compose -f docker-compose.json up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_webapp2_1 ... done
Creating docker-compose_webapp1_1 ... done
gaurav@learning-ocean:~/docker-compose$