Skip to content

Docker Compose

Target

This project is about Docker Compose. You will:

  • write a Docker Compose deployment
  • familiarize yourself with the basic commands of the Compose CLI docker compose

Tools

  • Try to complete the tasks below with the help of the slides and the cheatsheet.
  • If you have any problems, you will find a fold-out block for each task describing the solution.

Task 1 - Create and use a docker-compose.yml

In this section, you will familiarize yourself with the Compose file format and start the Docker Demo App using the Compose CLI docker compose.

  1. Create a new subfolder deployment of the workspace folder /home/coder/workspace.
  2. Create a new file compose.yml in the folder deployment.
  3. Open the file compose.yml.
  4. Copy the following content into the file:

    ---
    services:
      webapp:
        image: corewire/docker-demoapp:1.0.0
        ports:
          - 8080:5000
    

    • All containers of a Compose deployment are defined in the services block.
    • webapp defines a service. In this service you define,
      1. ) that the image corewire/docker-demoapp:1.0.0 is used and
      2. ) a port mapping of the container port 5000 to the host port 8080 so that the application can be reached at http://code-X.labs.corewire.de:8080.
  5. Change to the deployment folder in the terminal.

    Solution (click on the arrow if you get stuck)
    • If you are already in the Workspace folder, you can switch directly to the new folder with cd:
      cd deployment
      
    • If you are still in a subfolder of Workspace, first navigate to the workspace folder:
      cd ..
      
      Then change to the correct subfolder:
      cd deployment
      
  6. Start your service in the background.

    Solution (click on the arrow if you get stuck)
    • Use -d to start the container in the background.
      docker compose up -d
      
    • You can display all running containers of a compose deployment with the command docker compose ps.

    docker compose up -d

    • If you have defined more than one service, docker compose up -d starts all services.
    • If you only want to start individual services, use docker compose up -d <service_name>
  7. Display the logs of the webapp service.

    Solution (click on the arrow if you get stuck)
    • You can display the logs with or without the -f option. With -f newly appearing logs are displayed.
      docker compose logs -f webapp
      
  8. Open the URL http://code-X.labs.corewire.de:8080 in the browser, where X is your number. You should now see the demo app.

  9. Stop and remove the service again:

    docker compose stop webapp
    docker compose rm webapp
    
    or
    docker compose down
    

    Warning about docker compose down

    • docker compose down is a very destructive command.
    • If you have defined more than one service, docker compose down will stop all services, remove all containers and remove all local networks.
    • So if you only want to stop individual services, use docker compose stop and docker compose rm.

Task 2 - Volumes in Docker Compose

You have learned in previous chapters of the training that containers are 'stateless'. Stateless means that data written during the runtime of a container disappears as soon as the container is deleted. In this section, you will learn how to define volumes in the Compose file format.

  1. The Docker Demo App stores notes created in the web interface under the path /app/data/notes by default.
  2. Add a section volumes to your compose.yml file to the webapp service.

    Volume for service 'webapp'
    • Type: bind-mount
    • Local path: ./volumes/webapp-data
    • Mount path in the container: /app/data/notes
    • If you have forgotten the exact syntax, use the training material or the documentation of the Compose file format for Volumes.
    Solution (click on the arrow if you get stuck)

    The syntax is volumes: and below with indentation and - <hostpath>:<containerpath>:

    ---
    services:
      webapp:
        image: corewire/docker-demoapp:1.0.0
        ports:
          - 8080:5000
        volumes:
          - ./volumes/webapp-data:/app/data/notes
    
    Alternatively, there is also a long form, but this assumes that the folder /volumes/webapp-data already exists:
    ---
    services:
      webapp:
        image: corewire/docker-demoapp:1.0.0
        ports:
          - 8080:5000
        volumes:
          - type: bind
            source: ./volumes/webapp-data
            target: /app/data/notes
    

  3. Start the webapp service.

    Solution (click on the arrow if you get stuck)
    docker compose up -d webapp
    
  4. You should now see that a new folder volumes appears in your directory, in which a folder webapp-data is located. This folder should be empty.

  5. Now open the URL http://code-X.labs.corewire.de:8080 in the browser, where X is your number. You should now see the demo app.
  6. Create a note in the web interface of the demo app.
  7. You should now see in the folder volumes/webapp-data that a new file has been created, similar to note_2022-06-16T13:43:23.690467.txt.
  8. Stop and remove the service webapp.

    Solution (click on the arrow if you get stuck)

    To stop and remove use the following command:

    docker compose stop webapp
    docker compose rm webapp
    
    or
    docker compose down
    

  9. Start the webapp service.

    Solution (click on the arrow if you get stuck)
    docker compose up -d webapp
    
  10. Now open the web interface of the demo app again (http://code-X.labs.corewire.de:8080).

  11. You should now be able to see the note you just created.

Task 3 - Database Service

In this section you will define a new service that will start a MariaDB database server.

  1. Add a service database to your compose.yml file:

    Database Service 'database'
    • Name: database
    • "MYSQL_USER=example-user"
    • "MYSQL_PASSWORD=password"
    • "MYSQL_ROOT_PASSWORD=root_password "
    • Type: named volume
    • Name: database-volume
    • Mount path in container: /var/lib/mysql
    • Name: database-network
    Solution (click on the arrow if you get stuck)
    ---
    services:
      webapp:
        image: corewire/docker-demoapp:1.0.0
        ports:
          -  8080:5000
        volumes:
          - ./volumes/webapp-data:/app/data/notes
    
      database:
        image: mariadb:latest
        environment:
          - "MYSQL_USER=example-user"
          - "MYSQL_PASSWORD=password"
          - "MYSQL_ROOT_PASSWORD=root_password"
        volumes:
          - database-volume:/var/lib/mysql
        networks:
          - database-network
    
    volumes:
      database-volume:
    
    networks:
      database-network:
    
  2. Start the service database.

    Solution (click on the arrow if you get stuck)

    To start the service, use the following input:

    docker compose up -d database
    

  3. Display the logs of the database service.

    Solution (click on the arrow if you get stuck)

    To output the logs, use the following input:

    docker compose logs -f database
    

  4. If the database container has started successfully, you will see the following output at the end of the log stream:

    database_1 | 2022-06-16 14:42:06 0 [Note] Server socket created on IP: '0.0.0.0'.
    database_1 | 2022-06-16 14:42:06 0 [Note] Server socket created on IP: '::'.
    database_1 | 2022-06-16 14:42:06 0 [Note] mariadbd: ready for connections.
    database_1 | Version: '10.8.3-MariaDB-1:10.8.3+maria~jammy' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
    

Task 4 - Connecting the webapp to the database

In this section, we connect the Docker demo app to a database, i.e. the webapp service to the database service.

  1. On the web interface of the Docker Demo App (http://code-X.labs.corewire.de:8080) you see the following error message:

    Connection to MariaDB Server could not be established: Unknown MySQL server host 'database' (-5)
    
    This is because the Docker demo app is not connected to any database and the application expects a database server to be accessible under the DNS name "database" by default.

  2. Customize the service webapp by adding environment variables and a network:

    Service 'webapp'
    • "DATABASE_HOST=database "
    • "DATABASE_PORT=3306"
    • "DATABASE_USER=example-user"
    • "DATABASE_USER_PASSWORD=password "
    • Name: database-network
    Solution (click on the arrow if you get stuck)
    ---
    services:
      webapp:
        image: corewire/docker-demoapp:1.0.0
        ports:
          -  8080:5000
        volumes:
          - ./volumes/webapp-data:/app/data/notes
        networks:
          - database-network
        environment:
          - "DATABASE_HOST=database"
          - "DATABASE_PORT=3306"
          - "DATABASE_USER=example-user"
          - "DATABASE_USER_PASSWORD=password"
    
      database:
        image: mariadb:latest
        environment:
          - "MYSQL_USER=example-user"
          - "MYSQL_PASSWORD=password"
          - "MYSQL_ROOT_PASSWORD=root_password"
        volumes:
          - database-volume:/var/lib/mysql
        networks:
          - database-network
    
    volumes:
      database-volume:
    
    networks:
      database-network:
    
  3. Restart the webapp service.

    Solution (click on the arrow if you get stuck)

    To start the service, use the following input:

    docker compose up -d webapp
    

  4. Open http://code-X.labs.corewire.de:8080, the error message should now have disappeared.