- A Docker Image is a read-only template used to create [[Containerization|containers]].
- It includes everything needed to run an application, such as code, libraries, and environment variables.
- A container is a runnable instance of a Docker image.
- It is isolated from other containers and the host system.
- In multi-container setups (such as with Docker Compose), each container has its own file system, which is isolated from other containers.
- Docker Hub is a cloud-based registry where you can find and share Docker images.
- Images can be pulled from Docker Hub or pushed for others to use.
- A script containing a series of instructions on how to build a Docker image.
- Specifies the base image, application code, dependencies, and commands to run the application.
# Use the official Node.js image as a base
FROM node:14
# Set the working directory
WORKDIR /app
# Copy package.json and install dependencies
COPY package*.json ./
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the application port
EXPOSE 3000
# Command to run the application
CMD ["npm", "start"]
# Inside the Project Directory
# Build the Docker image
docker build -t my-node-app .
# Run the Docker container
docker run -p 3000:3000 my-node-app
- Multi-stage Builds allow for the creation of more efficient and smaller production images.
- Enable use of multiple
FROM
statements in aDockerfile
, each of which can use a different base image.
- Enable use of multiple
# Build stage
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm install --only=production
EXPOSE 3000
CMD ["node", "dist/main.js"]
# Build up to a specific stage
docker build --target builder -t myapp:build .
- A tool for defining and running multi-container Docker applications.
- Using a
docker-compose.yml
file, all of the application's services (such as databases), networks, and volumes can be configured in one place. - Each container has its own file system, which is isolated from other containers.
- Containers cannot access files or directories from other containers unless explicitly configured to do so.
- Volumes are used to share files or data between containers.
- They are managed by Docker and can be mounted into one or more containers.
- Anatomy
services
- where you define the various containers that make up your application.- Each service corresponds to a container and can include various configurations such as the image to use, build context, environment variables, and more.
- Services can refer to each other by their service names defined in the
docker-compose.yml
file.
build
- used to build a custom image for a service.- It points to the directory containing the
Dockerfile
.
- It points to the directory containing the
volumes
- used to persist data generated by and used by Docker containers.- Used to ensure data is not lost when containers are stopped.
- Commands
docker compose build
- builds the image.docker compose up
- starts all services defined in the file.docker compose down
- stops and removes containers, networks, volumes, and images defined in adocker-compose.yml
file.
my-fullstack-app/
├── frontend/
│ ├── src/
│ │ ├── App.js
│ │ └── index.js
│ ├── package.json
│ └── Dockerfile
├── backend/
│ ├── src/
│ │ └── index.js
│ ├── package.json
│ └── Dockerfile
├── docker-compose.yml
└── .env
# Backend Dockerfile
FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5000
CMD ["npm", "start"]
# Frontend Dockerfile
FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npx", "serve", "-s", "build"]
# docker-compose.yml
version: '3'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgres://user:password@db:5432/todos
depends_on:
- db
db:
image: postgres:13
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=todos
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
# Run Locally
docker compose build
docker compose up -d
docker compose down
Important
localhost
or 127.0.0.1
from within a container refers to the container’s own loopback interface, not the host machine or other containers. localhost
or 127.0.0.1
can be still be used (outside of Docker) to access services running on your host machine.
Containers communicate using the internal Docker network. A service (e.g. backend
) cannot use localhost
to connect to another service (e.g. db
) because localhost
would refer to the backend container itself. Instead, it should use the service name (db
) as defined in your docker-compose.yml
to connect to that service.
# Build an image from a `Dockerfile` in the current directory
docker build -t <image_name>:<optional_tag> .
# Create and start a container
docker run -p <host_port>:<container_port> <img_name>:<tag>
# Pull an image from a registry
docker pull <image>
# Push an image to a registry
docker push myregistry.com/<img_name>:<tag>
# List local images
docker images
# List running containers
docker ps
# Stop a running container
docker stop <container_id>
# Remove a container
docker rm <container_id>
# Clean up unused Docker objects
docker <object> prune # Object: network, volume, image, container
# View container logs
docker logs -f <container_id>
# Execute a command in a running container
docker exec -it <container_id> /bin/bash
# Docker Compose
# Start all services defined in docker-compose.yml
docker compose up
# Start specific services
docker compose up backend db
# Start services and rebuild images
docker compose up --build
# Stop and remove all containers, networks
docker compose down
# Also remove volumes
docker compose down -v
# Remove images as well
docker compose down --rmi all
# Build or rebuild all services
docker compose build
# Build specific services
docker compose build backend db
# List all containers
docker compose ps
# List containers for specific services
docker compose ps backend db
# View logs from all services
docker compose logs
# View logs for specific services
docker compose logs web db
# Run a command in a running container
docker compose exec backend npm run test
# Open a shell in a running container
docker compose exec db bash