Docker Compose, Hello World
Tags: docker, javascript
Published: 2022-11-25 19:22:14

## Let’s use docker-compose to create containers.

In my [previous post](https://dev.to/davidsabine/docker-hello-world-3093), we used the publicly available `hello world` image to create Docker containers.

Now, let’s use `docker-compose` to do the exact same thing.

1. Make a new folder on your drive somewhere. Call it anything you want.

2. Inside that new folder, create ONE file (for now) with the following name:

    ```bash
    .
    └── docker-compose.yml
    ```

3. Write these lines into the new `docker-compose.yml` file.

    ```yaml
    services:
      hello_world:
        image: hello-world
    ```
    
4. Run the command: `docker-compose up`.

    Docker will compose a new “compose project” (that’s what they call it) and, inside it, a new container is created using the publicly available `hello-world` image.
    
  - And note the name of the new container will be {your folder name}-{the image name}-{a number}. `docker container ls -a` to see list all your containers.
    
  - Important note, the [Docker Desktop GUI](https://docs.docker.com/desktop/), will show:
    
    - a compose project named {your foldername}
    - a container (as a child of the compose project) named {the image name}-{a number}

5. And try running the command again: `docker-compose up`.

    Unlike [the previous post](https://dev.to/davidsabine/docker-hello-world-3093), wherein a new container is produced each time you run `docker run hello-world`, a new container is **not** produced by `docker-compose up`; rather, Docker will attach to the existing container inside the “compose project” made in the previous and will run the command in the `hello-world` image.

## Now, let’s do the same thing, but this time we’ll add Dockerfile.

### Why would we want a Dockerfile? Why not do it all in `docker-compose.yml`?

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. (I stole that sentence from [Docker Docs](https://docs.docker.com/engine/reference/builder/).) Imagine **a single computer** that you can copy and reuse.

And a `docker-compose.yml` file lets us compose applications that use multiple containers. Imagine **a network of computers** that you can copy and reuse.

### Your Turn

6. In the folder you made in #1 above, create another file called “Dockerfile”:

    ```bash
    .
    ├── docker-compose.yml
    └── Dockerfile
    ```

7. In your new `Dockerfile`, add the following:

    ```yaml
    FROM hello-world
    ```
    
    That line will tell Docker to build an image from the publicy available `hello-world` image. (The same image used in #3 above.)

8. Now, we can tell docker-compose to use the new Dockerfile, as follows:

    ```yaml
    services:
      hello-world:
        build:
          context: .
    ```

    Interesting to note: docker will name the new artifacts exactly as in the previous step: {the folder name}-{the image name}-{a number}. But, we actually have some control of these details. Carry on…

9.  Modify your docker-compose as follows:

    ```yaml
    services:
      my-awesome-app:
        build:
          context: .
    ```

10. Run `docker-compose up`.

    Note the name of the new container is {the folder name}-**my-awesome-app**-{a number}.

11. Now, to understand the power of `docker-compose`, modify your file as follows:

    ```yaml
    services:
      my-awesome-app-1:
        build:
          context: .
      my-awesome-app-2:
        build:
          context: .
    ```

10. Run `docker-compose up`.

    Now, when you run `docker-container ls -a`, you’ll see **two** containers were created with the names:
    - {the folder name}-**my-awesome-app-1**-{a number}
    - {the folder name}-**my-awesome-app-2**-{a number}

    And both used the same `hello-world` image configured in `Dockerfile`.

## Takeaways

- Using `docker-compose`, you downloaded an image, created containers from that image, and ran a program on that image.

- Incorporating `Dockerfile`, you separated the concerns nicely: one file that describes a reusable computer; another file that describes a network of computers.