Photo by Ian Taylor on Unsplash
Docker and Docker Compose
Docker and Docker Compose: A Simple Introduction
Table of contents
Introduction
This article introduces you to Docker and Docker Compose. It provides an overview of what a Dockerfile is, and how to use Docker Compose to run multiple containers together. At the end, the article provides a example Dockerfile using a Node.js application.
Docker
"Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers." (from Wikipedia)
The above definition probably confused more than enlighten you! But we can use that definition to understand what Docker is. The first keyword to look at is "to deliver software in packages" - this gives an idea of what Docker's primary purpose is. Docker was built as a way to enable developers to easily package their software projects and distribute this software to either other developers or to deploy the software for customers to use. The second keyword is "OS-level virtualization" - Docker is a virtualization runtime which enables software that is packaged (called "containers") to run on any operating system. This means you can develop your project in Windows, and have your friend who uses MacOS run it without having to worry about dependencies and OS-level differences. The final keyword is "platform as a service products" - Docker is just one platform that provides you the ability to create and run containers. But this platform comes with a host of additional features like the container "marketplace" called Docker Hub.
Docker uses a Dockerfile to build an Image. This Image can be run using the Docker Engine as a Container.
Dockerfile
A Dockerfile is the "plan" or "instructions" that Docker uses to build your image. Let us take a look at an example Dockerfile:
# Use official Node.js image as base
FROM node:20
# Set working directory in the container
WORKDIR /app
# Copy package.json and package-lock.json (if present) to the working directory
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Compile TypeScript to JavaScript
RUN npm run build
# Expose the port for the server
EXPOSE 5000
# Start the server
CMD ["node", "./dist/index.js"]
FROM
: Tells Docker which base image to use. In this case it is using Node.js v20 which will be pulled from Docker Hub.WORKDIR
: Tells Docker to use the specified directory to build and run the code (called working directory). In this case it is/app
.COPY
: Tells Docker what files to copy from your project code to the working directory.RUN
: Tells Docker what commands to run. In this file, we use the run command to install dependencies and build the project.EXPOSE
: Tells Docker what port to expose the container so that we can interact with the container. In this case, we are using port 5000.CMD
: Tells Docker what command to run to start the server/application.
Dockerfiles differ from language to language (Java, Go etc.) and need to be customized as per your requirements.
Docker Compose
Most applications depend on another service like a database, or maybe consist of multiple services running together (a frontend, a server, and a database).
Docker Compose is an another file which lets you build and run containers which contain multiple images. These images might be ones you have created using a Dockerfile or an image which is available on the Docker Hub marketplace.
Let us take a look at an example docker-compose.yml file:
version: '3.8'
services:
mongo:
image: mongo:latest
container_name: mongo
ports:
- '27017:27017'
volumes:
- mongo-data:/data/db
server:
build:
context: ./
dockerfile: Dockerfile
container_name: server
ports:
- '5000:5000'
depends_on:
- mongo
environment:
MONGODB_URI: mongodb://mongo:27017/your_database_name
SERVER_PORT: 5000
volumes:
mongo-data:
In this file we are defining two "services":
mongo
: For the MongoDB database. There is also a volume calledmongo-data
used to store the database data.server
: For the Node.js express server. Thedockerfile
field indicates that Docker Compose will use the source Dockerfile to build the image and create the container.
Because of the depends_on
configuration in the server
definition, Docker will first start the mongo
service, and then start the server
service.
Example
If you want see an example on using Docker and Docker Compose, you can go to: https://github.com/anikeshk/ci-books
This sample project is a Node.js express server which uses MongoDB as the database. The Docker Compose file will run the database first, and then the server. Instructions on how to run and test the project are present in the README.md
.