Docker

Dockerfile

Docker Tutorial

Docker is a platform for developing, shipping, and running applications in containers. This tutorial will walk you through the basics of Docker, including installation, basic commands, and creating your first Docker container.


Table of Contents

  1. What is Docker?
  2. Installing Docker
  3. Basic Docker Commands
  4. Working with Docker Images
  5. Creating and Running Containers
  6. Dockerfile Basics
  7. Conclusion

What is Docker?

Docker is a platform that uses containerization to allow applications to be run in isolated environments. Containers are lightweight and provide consistent environments from development to production, making it easier to manage dependencies.

Benefits of Docker

  • Portability: Docker containers can run on any system that has Docker installed.
  • Scalability: Containers can easily scale to meet demand.
  • Efficiency: Containers share the host OS kernel, making them more lightweight than traditional VMs.

Installing Docker

On Linux (Ubuntu)

  1. Update your system:
    sudo apt update
    sudo apt install apt-transport-https ca-certificates curl software-properties-common
    
  2. Add Docker’s official GPG key:
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
  3. Set up the Docker stable repository:
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
  4. Install Docker Engine:
    sudo apt update
    sudo apt install docker-ce docker-ce-cli containerd.io
    

Basic Docker Commands

  • Check Docker version:
    docker --version
    
  • Run a test container:
    docker run hello-world
    
  • List running containers:
    docker ps
    
  • List all containers (including stopped ones):
    docker ps -a
    
  • Stop a container:
    docker stop <container_id>
    
  • Remove a container:
    docker rm <container_id>
    

Working with Docker Images

  • Search for an image on Docker Hub:
    docker search <image_name>
    
  • Download (pull) an image:
    docker pull <image_name>
    
  • List downloaded images:
    docker images
    
  • Remove an image:
    docker rmi <image_id>
    

Creating and Running Containers

  1. Run a container:

    docker run -d -p 80:80 nginx
    

    This runs the nginx container in detached mode (-d) and maps port 80 on the container to port 80 on the host.

  2. Access container logs:

    docker logs <container_id>
    
  3. Execute a command inside a running container:

    docker exec -it <container_id> /bin/bash
    

Dockerfile Basics

A Dockerfile is a script that contains a series of commands to create a Docker image.

Example Dockerfile

# Use an official Python runtime as a parent image
FROM python:3.8-slim

# Set the working directory
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Run the application
CMD ["python", "app.py"]

Dockerfile Basics

A Dockerfile is a script containing a series of instructions on how to build a Docker image. It defines the environment in which applications run, including the operating system, application code, dependencies, and any other files necessary to run the application.

Structure of a Dockerfile

A Dockerfile is typically composed of a series of instructions. Each instruction creates a layer in the image, and these layers are cached to optimize builds. Below are common Dockerfile instructions:

1. FROM

The FROM instruction sets the base image for the subsequent instructions. It is the first command in a Dockerfile.

FROM ubuntu:20.04

2. MAINTAINER (deprecated)

The MAINTAINER instruction sets the author field of the generated images. This instruction is deprecated in favor of using LABEL.

MAINTAINER Your Name <your.email@example.com>

3. LABEL

The LABEL instruction adds metadata to the image, such as a description, version, or maintainer information.

LABEL version="1.0" description="My Sample Application"

4. RUN

The RUN instruction executes commands in a new layer on top of the current image and commits the results. This is often used to install software packages.

RUN apt-get update && apt-get install -y curl

5. COPY

The COPY instruction copies files or directories from the host filesystem into the image. It preserves the original file permissions.

COPY . /app

6. ADD

The ADD instruction is similar to COPY, but it can also extract TAR files and fetch files from URLs. It is generally recommended to use COPY unless you need the specific functionality of ADD.

ADD archive.tar.gz /app

7. CMD

The CMD instruction specifies the default command to run when the container starts. There can only be one CMD instruction; if multiple are specified, only the last one takes effect.

CMD ["python", "app.py"]

8. ENTRYPOINT

The ENTRYPOINT instruction configures a container to run as an executable. Unlike CMD, it does not get overridden by command-line arguments when you run the container.

ENTRYPOINT ["python"]
CMD ["app.py"]

9. ENV

The ENV instruction sets environment variables that can be accessed by the running application.

ENV APP_ENV production

10. EXPOSE

The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. It does not publish the port, but serves as documentation.

EXPOSE 8080

11. WORKDIR

The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY, and ADD instructions that follow in the Dockerfile.

WORKDIR /app

Best Practices

  1. Minimize Image Size: Use minimal base images to reduce the overall size of the final image. For example, use alpine images where possible.

  2. Use Multi-Stage Builds: Use multi-stage builds to separate the build environment from the runtime environment, reducing the final image size.

  3. Leverage Caching: Order commands to maximize the use of cached layers. Place less frequently changing instructions earlier in the Dockerfile.

  4. Avoid Using latest: Specify exact versions of base images to ensure reproducibility and avoid unexpected changes.

  5. Clean Up After Installations: Remove unnecessary files and packages after installations to keep the image size down.

Example Dockerfile

Here’s a simple example of a Dockerfile for a Python application:

# Base image
FROM python:3.9-slim

# Set the working directory
WORKDIR /app

# Copy requirements file and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Expose the port the app runs on
EXPOSE 5000

# Define the command to run the app
CMD ["python", "app.py"]

This example Dockerfile builds a Docker image for a Python application by installing dependencies, copying the application code, and specifying the command to run the application.

Conclusion

Dockerfiles are a powerful way to define and automate the deployment of applications in containers. Understanding the basic instructions and best practices will help you create efficient and maintainable Docker images.

# Stage 1: Build the application using Maven
FROM maven:3.8.6-openjdk-11 AS build
WORKDIR /app

# Copy the Maven project files
COPY pom.xml .
COPY src ./src

# Build the application
RUN mvn clean package -DskipTests

# Stage 2: Prepare the Tomcat image
FROM tomcat:9.0.73-jdk11-openjdk

# Remove the default webapps
RUN rm -rf /usr/local/tomcat/webapps/*

# Copy the WAR file from the build stage to the Tomcat webapps directory
COPY --from=build /app/target/*.war /usr/local/tomcat/webapps/app.war

# Expose the Tomcat port
EXPOSE 8080

# Start Tomcat
CMD ["catalina.sh", "run"]

Add vs Copy

Feature COPY ADD
Basic Function Copies files/directories from the host to the image. Copies files/directories from the host to the image, and can also fetch files from URLs.
Extraction Does not extract compressed files. Automatically extracts compressed files (e.g., .tar, .gz).
URL Support Does not support fetching files from URLs. Can fetch files from URLs.
Use Case Recommendation Recommended for simple file copying tasks. Recommended for use cases requiring extraction or fetching from URLs.
File Permissions Preserves original file permissions. Preserves original file permissions.
Performance Generally faster for simple copy tasks. May be slower due to extraction or downloading.
Best Practice Preferred for copying files due to simplicity and clarity. Use only when its additional features are needed.

ENTRYPOINT VS CMD

Feature CMD ENTRYPOINT
Purpose Provides default commands and/or arguments for the container. Configures the container to run as an executable.
Overriding Behavior Can be overridden by command-line arguments when the container is run. Arguments passed at runtime are appended to the ENTRYPOINT command.
Default Command Used to specify the command that runs when the container starts. Used to specify the executable that runs when the container starts.
Usage Typically used for defining default commands. Used when the container needs to behave like a standalone executable.
Multiple Instructions Only the last CMD instruction takes effect if multiple are specified. Multiple ENTRYPOINT instructions do not stack; only the last one takes effect.
Best Practice Best for default arguments. Use alongside ENTRYPOINT for flexibility. Best for defining the main command that should always run.

Examples

Example of CMD

In this example, CMD is used to specify default arguments for the command:

FROM ubuntu:20.04

# Set the working directory
WORKDIR /app

# Copy application files
COPY . .

# Specify the default command to run when the container starts
CMD ["python", "app.py"]

Example of ENTRYPOINT

In this example, ENTRYPOINT is used to define the main command that should always run:

FROM ubuntu:20.04

# Set the working directory
WORKDIR /app

# Copy application files
COPY . .

# Define the executable that runs when the container starts
ENTRYPOINT ["python"]

# Specify default arguments for the ENTRYPOINT
CMD ["app.py"]