Docker Beginner Tutorial

Let’s assume you are sold on Docker – you need and love Docker.

How is it used?

On your computer:
– install docker (docker desktop is most popular, podman is gaining ground)
– develop an application adjusting your Dockerfile
– use Dockerfile to build a “image” – a portable package of your app
– test locally by running the image as a “containerized process” (container)
– upload image it to hosted image registry (typically DockerHub)

On your server:
– install docker engine
– pull image from hosted image registry
– run the image as a “container”

Development Workflow: Dockerfile -> Image -> Container
Dockerfile is instructions to build an application environment and run application
Image is a portable package built by running Dockerfile with everything needed to run the application.
Container is a running instance of an image

Note: some people say the image is like a recipe, but it actually has all the code needed to run your application.

How to write a Dockerfile

Remember Dockerfiles are instructions for building an image. Include s:
– setting a base image to build upon
– setting environment variables
– setting a “working directory” (WORKDIR) of the image
– running COPY, RUN, CMD commands to execute inside WORKDIR

WORKDIR – “While building the image, change the working directory to /code. If /code doesn’t exist yet in the image, create it inside the image.”
COPY – “Copy these files from the local machine into the image WORKDIR”
RUN – “Execute this command in the container”

Bash
# Dockerfile

# Pull base image
FROM python:3.10.4-slim-bullseye

# Set environment variables
ENV PIP_DISABLE_PIP_VERSION_CHECK 1
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Set work directory for the image
# Automatically creates the /code directory (in the image)
# Sets it as the current directory for all following commands:
# RUN, CMD, COPY, and ENTRYPOINT 
WORKDIR /code

# Note: Docker uses / (the root directory) by default,
# which is usually not what you want —
# it's better to work in an isolated app folder like /code, /app, or /srv/app.


# Install dependencies (with layer caching)
# 1. copy requirements file into the image
# 2. run pip install

# The COPY command takes two parameters:
# 1. what local file(s) to copy into the image,
# 2. where you want the file(s) to be copied (relative to WORKDIR).

# In this case, we are copying the existing requirements.txt file 
# from our local computer into the current working directory
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# Note: We usually install dependencies before copying the rest of the app
# to take advantage of Docker's layer caching:
# So RUN pip install happens before COPY . .

# Copy project
# copy the current directory on our local filesystem (.)
# into the working directory (.) of the image.
COPY . .

Now you can run the image as a container

Bash
# builds the image "." is where the Dockerfile is located
docker build .

docker images
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
<none>        <none>    0cc1074c90de   3 minutes ago    253MB

# Note: returns immediately and doesnt start the server because there is no CMD to do so
docker run 0cc1074c90de

# Run a django server
# Note: you need to add 0.0.0.0 to allowed hosts
# 0.0.0.0 tells Django to accept requests from any IP address, including the host machine
# 127.0.0.1:8000	is only accessible inside the container
docker run -p 8000:8000 0cc1074c90de python manage.py runserver 0.0.0.0:8000

Docker compose

Docker compose allows you to set up multi-container applications
– you will soon have separate containers for the web server, database, cache
– here you have one container “web”

Bash
# docker-compose.yml
version: "3.9"
services:
  web:
    build: .
    ports:
      # “Map port 8000 inside the container to port 8000 on my host machine.”
      - "8000:8000"
    # 0.0.0.0 means listens for incoming requests on any IP address inside the container.
    command: python manage.py runserver 0.0.0.0:8000
    
    # visit http://127.0.0.1:8000
    # “Send this request to port 8000 on my own machine.”
    # Docker receives that request and passes it to your Django container

    # Sync with the local filesystem:
    # Take the current directory on my host machine (the .), 
    # and mount it into the container at the /code path.
    # Develop without rebuilding the Docker image for every Python file change.
    volumes:
      - .:/code  

You can now use docker compose to run the container

Bash
docker-compose up 

# visit 127.0.0.1:8000

docker-compose down

Learn more:

Previous: https://theptrk.com/wp-admin/post.php?post=1585&action=edit