Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

bendahl/docker-todo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cheat Sheet

This cheat sheet is meant to provide a high level overview of the project and help you to get started with the Docker examples provided.

Motivation

This project aims to provide a simple playground for multi container Docker projects and to serve as a starting point to further examine Docker.

Prerequisites

This project uses Java (11), Maven and Docker along with Docker Compose. You will only need to install Java on your system if you're planning on building the applications without using Docker (for local development, etc...). Otherwise, the provided Dockerfiles will take care of this, by using multistage builds. If you're not using Maven, don't worry, simply use one of the wrapper scripts (mvnw*) in order to build the project. For all other dependencies you'll find links that will provide further information here:

IMPORTANT: If you're working on Linux, do not simply install Docker and Docker Compose straight from your distro's repositories, as the versions found there may be outdated. Make sure to check the version first. All examples were created and tested using Version 1.13 of Docker and Docker Compose. So anything >= Version 1.13 should be ok.

Project Structure

The below tree shows the basic project file structure and gives a few hints on what you will find where. Use this as your map. More details are explained further on in the document.

.
├── backend                                                     // the backend service project root
│   ├── Dockerfile                                              // this Dockerfile will build an image for the backend - note that you'll need to perform a Maven build first
│   ├── mvnw                                                    // Maven wrapper script for Mac/Linux/Cygwin
│   ├── mvnw.cmd                                                // Maven wrapper script for Windows
│   ├── pom.xml                                                 // Maven pom.xml with the basic build settings
│   └── src                                                     // Java sources
│       ├── main
│       │   ├── java
│       │   │   └── de
│       │   │       └── bendahl
│       │   │           ├── SwaggerConfig.java                  // Swagger setup (for more information see: http://swagger.io/)
│       │   │           ├── TodoApplication.java                // the main entry point of the app
│       │   │           ├── TodoEndpoint.java                   // REST endpoint
│       │   │           ├── Todo.java                           // the Todo entity class for DB and JSON mapping
│       │   │           └── TodoRepository.java                 // Spring JPA repository that handles data access
│       │   └── resources                                       // non-code resources used by the backend project
│       │       ├── application.properties                      // app settings
│       │       └── data.sql                                    // initial data to populate the in H2 DB
│       └── test
│           └── java
│               └── de
│                   └── bendahl
│                       └── TodoApplicationTests.java           // standard unit test generated by Spring Boot
├── docker-compose.yml                                          // basic docker-compose file that will deploy frontend and backend, using the Docker Hub repositories
├── frontend                                                    // the frontend service project root
│   ├── Dockerfile                                              // this Dockerfile will build an image for the frontend - note that you'll need to perform a Maven build first 
│   ├── mvnw                                                    // Maven wrapper script for Mac/Linux/Cygwin
│   ├── mvnw.cmd                                                // Maven wrapper script for Windows
│   ├── pom.xml                                                 // Maven pom.xml with the basic build settings
│   └── src                                                     // Java sources
│       ├── main
│       │   ├── java
│       │   │   └── de
│       │   │       └── bendahl
│       │   │           ├── DemoFrontendApplication.java        // Main entry point of the frontend application
│       │   │           ├── TodoChangeListener.java             // interface used to create a change event binding 
│       │   │           ├── Todo.java                           // todo class that maps to and from JSON
│       │   │           ├── TodoLayout.java                     // layout that is used to display the todo list items
│       │   │           ├── TodoList.java                       // controls the behavior of the actual todo list
│       │   │           ├── TodoService.java                    // the service that handles all backend calls
│       │   │           └── TodoUI.java                         // setup of basic layout and components of the application
│       │   └── resources
│       │       ├── application.properties                      // app settings - the backend URL is setup here
│       │       ├── static                                      // not needed in this case - generated by Spring Boot
│       │       └── templates                                   // not needed in this case - generated by Spring Boot
│       └── test
│           └── java
│               └── de
│                   └── bendahl
│                       └── DemoFrontendApplicationTests.java   // standard unit test generated by Spring Boot
└── README.MD                                                   // Start here ;-)

The Backend

The backend consists of a REST service that is built on top of Spring Boot. OpenAPI is integrated in the service in order to make it easy to play around with a few simple requests and get a feel for what it actually does. Besides Java and Spring Boot, H2 DB is used as a data store in order to keep things simple and not require an addtional database(container) to be set up. The backend listens on port 8081 and the base URL is: http://HOSTNAME_GOES_HERE:8081/todos. The swagger web ui is located at: http://HOSTNAME_GOES_HERE:8081/swagger-ui.html. The OpenApi schema is located at: http://localhost:8081/v3/api-docs. The health status of the backend service is exposed using the Spring Boot Actuator and exposed at http://localhost:8080/actuator/health.

Note that the H2 DB is set up to use file storage, in order to be able to use this project to not only demonstrate networking in Docker, but also some storage basics. As long as the backend container is not removed, the data will not be lost upon container restart/stop. The default storage location of the db is the file /tmp/todo.mv.db within the container (see application.properties for details). This should be a sensible default in most cases. If, however, you wish to override this behavior, it's as simple as setting the environment variable DB_FILENAME in order to change it. The format of the filename is <path>/<filename>, where filename will automatically be expanded to "filename.mv.db".

Building the Docker image:

  • cd into the backend directory first
  • then enter the following (omitting the ":1.0" will create an image tagged as "latest"): docker build -t todo-backend:1.0 .

Creating and running a container based on your local image: docker run -d --name backend -p 8081:8081 todo-backend:1.0

This will essentially create and immediately start a new container named "backend" based on your local image created above. You can now connect to it on the exposed port 8081.

Useful commands:

  • docker ps: See a list of all running containers

  • docker stop [CONTAINER]: Stop a container

  • docker ps -a: See a list of all containers (running or not) and their status

  • docker rm [CONTAINER]: Delete a container

  • docker rmi [IMAGE:TAG]: Delete an image

The Frontend

The frontend application is a basic Vaadin Todo app, largely taken from https://github.com/vaadin-marcus/spring-boot-todo/. It also uses Java, Spring Boot and Maven as its stack. It is exposed on port 8080 by default. Simply navigate to the url http://HOSTNAME_GOES_HERE:8080 in your favorite browser to see the web ui.

In order to successfully run the frontend, make sure that the backend is up and running and listening for connections on port 8081 (default setting of the backend). You will also need to specify the environment variable BACKEND_HOSTNAME, since the frontend uses this variable to retrieve the actual host name of the backend application.

Additional information: When using Docker, a container's host name usually matches its name. Therefore, if you started the backend container like described above, its host name will be "backend". Also note that the two containers will have to be on the same bridge network or, alternatively, use the host network (not recommended) in order to communicate with each other. All in all this can be achieved in three easy steps, described in the following section.

Running frontend and backend (not using docker-compose):

  • Create a bridge network (called 'matrix' in this example): docker network create matrix
  • Run the backend container: docker run -d --name backend --network matrix todo-backend:1.0 backend/.
  • Run the frontend container: docker run -d --name frontend --network matrix -p 80:8080 -e BACKEND_HOSTNAME=backend todo-frontend:1.0 frontend/.

This will essentially create a new bridge network called 'matrix' and connect two containers (frontend and backend) to it. Since both containers are on the same bridge network, they will be able to reach each other over tcp. Therefore there is no need to expose any port for the backend. The frontend, on the other hand, will need to be reachable from the host network, so you can navigate to the web ui using your browser. That's the reason for the '-p 80:8080' in the frontend call above. Also, don't forget to set the environment variable BACKEND_HOSTNAME when running the frontend. Otherwise the service will fail to startup, since it doesn't know the backend's host name.

Useful commands:

  • docker ps: See a list of all running containers

  • docker stop [CONTAINER]: Stop a container

  • docker ps -a: See a list of all containers (running or not) and their status

  • docker rm [CONTAINER]: Delete a container

  • docker rmi [IMAGE:TAG]: Delete an image

  • docker network create [NETWORK]: Create a new network

  • docker network ls: List existing networks

  • docker network rm [NETWORK]: Delete existing network

Docker Compose File

If you wold like to run the full example (front- and backend) without going through the hassle of creating your own network and manually running the containers, you may also use docker-compose to automate the whole process, including the creation of the two images. Note, however, that you will need to successfully build the two jar files (frontend and backend) first in order to build the images.

Running the examples via docker-compose:

  • Build the backend: cd backend && mvn clean install && cd ..
  • Build the frontend: cd frontend && mvn clean install && cd ..
  • Now run the example using docker-compose: docker-compose up -d (the -d ensures that the processes run in the background)
  • Open up http://localhost in your favorite browser to see the result

NOTE THAT THIS WILL FAIL WHEN USING ROOTLESS DOCKER, SINCE PORT 80 IS A PRIVILEGED PORT. EITHER USE ANOTHER PORT IN THE COMPOSE FILE OR USE DOCKER WITH ROOT.

Useful commands:

  • docker-compose up: Run containers according to the docker-compose.yml. Stdout will be forwarded.
  • docker-compose up -d: Run containers according to the docker-compose.yml. Processes will be run in the background.
  • docker-compose ps: View running containers and their status.
  • docker-compose stop: Stop the running containers.
  • docker-compose down: Stop and delete the running containers and the newly created network.

Credits

Special thanks goes to Marcus Hellberg for his excellent Vaadin example that really did prove to be a great time saver when creating the frontend application. The original Vaadin project is located here on Github at: https://github.com/vaadin-marcus/spring-boot-todo/

Miscellaneous

I hope that this little project will be useful for you in your quest to learn more about Docker and hopefully provide a fun playground to get started with multi container apps. Let me know if you've got any further ideas/suggestions! Feel free to clone the heck out of this repo and reuse whatever part you want. Cheers!