❌

Reading view

There are new articles available, click to refresh the page.

Docker Ep 9: The Building Blocks – Detailed Structure of a Dockerfile

Alex now knows the basics, but it’s time to get their hands dirty by writing an actual Dockerfile.

The FROM Instruction: Choosing the Foundation

The first thing Alex learns is the FROM instruction, which sets the base image for their container. It’s like choosing the foundation for a house.

  • Purpose:
    • The FROM instruction initializes a new build stage and sets the Base Image for subsequent instructions.
  • Choosing a Base Image:
    • Alex decides to use a Python base image for their application. They learn that python:3.9-slim is a lightweight version, saving space and reducing the size of the final image.

FROM python:3.9-slim

Example: Think of FROM as picking the type of bread for your sandwich. Do you want white, whole wheat, or maybe something gluten-free? Your choice sets the tone for the rest of the recipe.

The LABEL Instruction: Adding Metadata (Optional)

Next, Alex discovers the LABEL instruction. While optional, it’s a good practice to include metadata about the image.

  • Purpose:
    • The LABEL instruction adds metadata like version, description, or maintainer information to the image.
  • Example:
    • Alex decides to add a maintainer label:

LABEL maintainer="alex@example.com"

Story Note: This is like writing your name on a sandwich wrapper, so everyone knows who made it and what’s inside.

The RUN Instruction: Building the Layers

The RUN instruction is where Alex can execute commands inside the image, such as installing dependencies.

  • Purpose:
    • The RUN instruction runs any commands in a new layer on top of the current image and commits the results.
  • Example:
    • To install the Flask framework, Alex writes:

RUN pip install flask

They also learn to combine commands to reduce layers:


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

Story Note: Imagine slicing tomatoes and cheese for your sandwich and placing them carefully on top. Each ingredient (command) adds a layer of flavor.

The COPY and ADD Instructions: Bringing in Ingredients

Now, Alex needs to bring their application code into the container, which is where the COPY and ADD instructions come into play.

  • COPY:
    • The COPY instruction copies files or directories from the host filesystem into the container’s filesystem.
  • ADD:
    • The ADD instruction is similar to COPY but with additional features, like extracting compressed files.
  • Example:
    • Alex copies their application code into the container:

COPY . /app

Story Note: This is like moving ingredients from your fridge (host) to the counter (container) where you’re preparing the sandwich.

The WORKDIR Instruction: Setting the Workspace

Alex learns that setting a working directory makes it easier to manage paths within the container.

  • Purpose:
    • The WORKDIR instruction sets the working directory for subsequent instructions.
  • Example:
    • Alex sets the working directory to /app:

WORKDIR /app

Story Note: This is like setting up a designated area on your counter where you’ll assemble your sandwichβ€”keeping everything organized.

The CMD and ENTRYPOINT Instructions: The Final Touch

Finally, Alex learns how to define the default command that will run when the container starts.

  • CMD:
    • Provides defaults for an executing container, but can be overridden.
  • ENTRYPOINT:
    • Configures a container that will run as an executable, making it difficult to override.
  • Example:
    • Alex uses CMD to specify the command to start their Flask app:

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

Story Note: Think of CMD as the final step in making your sandwichβ€”like deciding to add a toothpick to hold everything together before serving.

Below is an example Dockerfile of a flask application,


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

# Set the working directory in the container
WORKDIR /app

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

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Breakdown of the Dockerfile:

  1. FROM python:3.9-slim:
    • This line specifies the base image. In this case, it uses a slim version of Python 3.9, which is lightweight and sufficient for a simple Flask application.
  2. WORKDIR /app:
    • This sets the working directory inside the container to /app. All subsequent commands will be run inside this directory.
  3. COPY . /app:
    • This copies everything from your current directory on the host machine into the /app directory inside the container.
  4. RUN pip install –no-cache-dir -r requirements.txt:
    • This installs the necessary Python packages listed in the requirements.txt file. The --no-cache-dir option reduces the image size by not caching the downloaded packages.
  5. EXPOSE 80:
    • This makes port 80 available for external access. It’s where the Flask application will listen for incoming requests.
  6. ENV NAME World:
    • This sets an environment variable NAME to β€œWorld”. You can access this variable in your Python code.
  7. CMD [β€œpython”, β€œapp.py”]:
    • This tells the container to run the app.py file using Python when it starts.

Example Flask Application (app.py):

To complete the example, here’s a simple Flask application you can use:


from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    name = os.getenv('NAME', 'World')
    return f'Hello, {name}!'

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

Example requirements.txt:

And here’s the requirements.txt file listing the dependencies for the Flask app:


Flask==2.0.3

Building and Running the Docker Image:

  1. Build the Docker image using the Dockerfile:
docker build -t my-flask-app .

2. Run the Docker container:


docker run -p 4000:80 my-flask-app
  • This maps port 4000 on your host machine to port 80 in the container.

Open your browser and go to http://localhost:4000, and you should see β€œHello, World!” displayed on the page.

You can customize the ENV NAME in the Dockerfile or by passing it as an argument when running the container:


docker run -p 4000:80 -e NAME=Alex my-flask-app

This will display β€œHello, Alex!” instead.

❌