This repository contains the code and resources for the Docker Workshop.
In this hands-on session, you will learn how to leverage Docker to containerize a simple Node.js Chat App:
flowchart TD
U1((User 1)) & U2((User 2)) & U3((User 3)) --> F
F[Next.js Frontend] --> B
B[Express.js Backend] --> DB[(MongoDB)]
- Node.js: Ensure you have Node.js installed on your machine. You can download it from nodejs.org.
This workshop is designed to work on Node.js 22 LTS, and may not work on other versions.
- Docker: Ensure you have Docker installed on your machine. Refer to the official Docker installation guide for instructions.
-
Clone this repository:
git clone https://github.com/yourusername/docker-workshop.git
-
Authenticate with GitHub Container Registry (ghcr) to push images: Replace
GITHUB_USERNAMEwith your GitHub username andGITHUB_TOKENwith a personal access token that haswrite:packagesscope.echo $GITHUB_TOKEN | docker login ghcr.io -u GITHUB_USERNAME --password-stdin
Docker can be used to spin up development services quickly.
Suppose you where working on the Express.js backend of the Chat App, which depends on MongoDB.
You can use Docker to run MongoDB in a container on your local machine without installing it directly.
-
Run the MongoDB container:
docker run \ --rm \ -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=secret \ mongodb/mongodb-community-server:8.0.9-ubi9 -
In a new terminal, configure the backend to connect to the MongoDB instance by creating
.envfile inbackenddirectory with the following content:MONGO_URL=mongodb://admin:secret@localhost:27017 -
Start the backend server, assuming you are already in the
backenddirectory:npm install npm run dev
Now that you have the backend working in development, let's containerize it.
-
Write a
Dockerfilein thebackenddirectory to build thebackendcontainer.- Compile the TypeScript code to JavaScript with
tsc - Set the container command run the built JavaScript code with
node
If you get stuck refer to the solution
- Compile the TypeScript code to JavaScript with
-
Build the Docker image, tagging it for publishing to ghcr.
Replace
GITHUB_USERNAMEwith your GitHub username:docker build -t backend ghcr.io/GITHUB_USERNAME/chat-backend:latest
-
Push the image to GitHub Container Registry:
Replace
GITHUB_USERNAMEwith your GitHub username:docker push ghcr.io/GITHUB_USERNAME/chat-backend:latest
Building the frontend container is similar to the backend:
-
Write a
Dockerfilein thefrontenddirectory to build thefrontendcontainer. Tips & tricks:-
Do you need to keep the
node_modulesin the final image? What is minimal set of files you need to run the frontend? -
Maybe Next.js Docker documentation could help?
-
Try to use multi-stage builds
FROM ... AS ...to keep the final image small.If you get stuck refer to the solution
-
-
Build the Docker image, tagging it for publishing to ghcr.
Replace
GITHUB_USERNAMEwith your GitHub username:docker build -t frontend ghcr.io/GITHUB_USERNAME/chat-frontend:latest
-
Push the image to GitHub Container Registry:
Replace
GITHUB_USERNAMEwith your GitHub username:docker push ghcr.io/GITHUB_USERNAME/chat-frontend:latest
Getting multiple containers to work together can be tricky, especially when they depend on each other.
docker run ... mongodb
docker run ... chat-backend
docker run ... chat-frontend
Docker Compose is a tool that allows you to define and run multi-container deployments easily.
-
Create a
.envfile in the define environment variables to be used in thedocker-compose.ymlfile:MONGO_USERNAME=admin MONGO_PASSWORD=secret
-
Write a
docker-compose.ymlfile in the root directory of the repository to define the services:-
mongodb: Use the official MongoDB image, similar to how you ran it in developmentj0.- Direct MongoDB to use
MONGO_USERNAME&MONGO_PASSWORDto initialize the root user. - Map the port
27017to your host machine. - Use a named volume to persist data across container restarts.
- Direct MongoDB to use
-
backend: Use theghcr.io/GITHUB_USERNAME/chat-backend:latestimage.- Use the build specification to build the image from the
backenddirectory. - Direct backend to to connect to the MongoDB instance with
MONGO_URLenvironment variable. - Map the port
3001to on your host machine to the backend container. - Add a
restartpolicy to restart the container starts before MongoDB is ready.
- Use the build specification to build the image from the
-
frontend: Use theghcr.io/GITHUB_USERNAME/chat-frontend:latestimage.- Use the build specification to build the image from the
frontenddirectory. - Direct frontend to connect to the backend instance with
NEXT_PUBLIC_BACKEND_URLenvironment variable. - Map the port
3000on your host machine to the frontend container.
- Use the build specification to build the image from the
If you get stuck refer to the solution
-
-
Bring up the services with Docker Compose:
docker compose up
-
Open your browser and navigate to
http://localhost:3000to see the Chat App in action. -
Clean up the resources when you are done:
docker compose down -v
Docker Compose is fine for development and testing, but in production would want to use Kubernetes for orchestration.
Converting the docker-compose.yml file into Kubernetes manifests is left as a challenge for the reader.