Write Better Dockerfile

Sami Salih İbrahimbaş
GoTurkiye
Published in
7 min readDec 16, 2022

Step by Step and Logic

Today I’m going to talk about how to write a Dockerfile that is safer, builds faster, has less volume and makes the first run fast.

But before I get to that, I’II go step by step talking about why we need it.

Article Cover

Why do we need a Dockerfile?

Docker is a containerization tool that allows us to create a container with all the necessary dependencies to run our application.

What is a container?

A container is a virtual machine that runs on the host machine. It is lighter than a virtual machine because it does not have a full operating system, but only the necessary dependencies to run our application.

What is the container?

What does the container have?

The container has the necessary dependencies to run our application. It can be a database, a web server, a programming language, etc.

More about containers: What is a container?

What is a Dockerfile?

The Dockerfile is a file that contains the instructions to build the image that will be used to create the container.

What is a Docker Image?

An image is a template that contains all the necessary dependencies to run our application.

Actually it is a snapshot of the container.

How to Write a Basic Dockerfile?

In this section, we will see how we can create a simple Dockerfile.

Step 1: Use a base image

The first thing we need to do is to choose a base image. The base image is the image that will be used to create the container.

Step 2: Copy the files

The next step is to copy the files to the container. The files that will be copied are the files that will be used to run the application.

Step 3: Install the dependencies

The next step is to install the dependencies. The dependencies are the dependencies that will be used to run the application.

Step 4: Expose the port

The next step is to expose the port. The port is the port that will be used to run the application.

Step 5: Run the application

The next step is to run the application.

Example

# Use a base image
FROM golang:1.19-alpine

# Copy the files
COPY . /app

# Install the dependencies
RUN go mod download

# Expose the port
EXPOSE 8080

# Run the application
CMD ["go", "run", "main.go"]

What did we do here?

We created a Dockerfile that uses the golang:1.19-alpine image as a base image, copies the files, installs the dependencies, exposes the port 8080 and runs the application.

In fact, the application we make here is never a preferred situation for production.

Because here golang runs as a runtime. However, golang is a language that can give executable for us. Things can be safer and faster if we produce an executable.

How To Write a Dockerfile Dor Production?

In this section, we will focus on a more preferable example then the previous section.

Step 1: Use a base image

The first thing we need to do is to choose a base image. The base image is the image that will be used to create the container.

Step 2: Copy the files

The next step is to copy the files to the container. The files that will be copied are the files that will be used to run the application.

Step 3: Install the dependencies

The next step is to install the dependencies. The dependencies are the dependencies that will be used to run the application.

Step 4: Build the application

The next step is to build the application.

Step 5: Expose the port

The next step is to expose the port. The port is the port that will be used to run the application.

Step 6: Run the application

The next step is to run the application.

Example

FROM golang:1.19-alpine

# Copy the files
COPY . /app

# Install the dependencies
RUN go mod download

# Build the application
RUN go build -o main .

# Expose the port
EXPOSE 8080

# Run the application
CMD ["./main"]

What did we do here?

We created a Dockerfile that uses the golang:1.19-alpine image as a base image, copies the files, installs the dependencies, builds the application, exposes the port 8080 and runs the application.

Actually, this method is used by some people in production. However, this is insufficient.

Because here we created an executable with golang and when our container runs we exec this executable. But the golang continues to live with our container. Also, as our project grows, we may not need to include various files in production. So we have a better method.

How To Write a Better Dockerfile?

In this section we will learn how to create a Dockerfile to create a really safe, fast and lightweight docker container.

Step 1: Use a base image

The first thing we need to do is to choose a base image. The base image is the image that will be used to create the container.

Step 2: Use a multi stage build

The multi stage build is a technique that allows us to create a Dockerfile with multiple stages. Each stage is a Dockerfile that will be used to create a container. The last stage is the one that will be used to create the container that will be used to run the application.

Step 3: Use a .dockerignore file

The .dockerignore file is a file that contains the files and folders that will be ignored when building the image.

Example

The copy line here has been edited. Thanks to Mehmet Sezer for the correction.

# Use a smaller base image
FROM golang:1.19-alpine AS builder

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download all dependencies.
# Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download

# Build the application
RUN go build -o main .

# Use a smaller base image
FROM alpine:3.14 AS runner

# Copy the files
COPY --from=builder /app/main /app/main

# Expose the port
EXPOSE 8080

# Run the application
CMD ["./app/main"]

What did we do here?

We created a Dockerfile that uses the golang:1.19-alpine image as a base image, copies the files, installs the dependencies, builds the application, uses the alpine:3.14 image as a base image, copies the files, exposes the port 8080 and runs the application.

How To Build and Run The Image?

In this section, we will see how to create and run a Docker Image with the Dockerfile we created.

Step 1: Build the image

The first thing we need to do is to build the image. The image is the image that will be used to create the container.

Step 2: Run the container

The next step is to run the container. The container is the container that will be used to run the application.

Example

# Build the image
docker build -t go-docker .

# Run the container
docker run -p 8080:8080 go-docker

How Can I Tell If It Is Fast and Light?

In this section, we will learn how to see if we have really changed something in Docker with our Dockerfile changes.

Step 1: Check the size of the image

The first thing we need to do is to check the size of the image. The size of the image is the size of the image that will be used to create the container.

Step 2: Check the size of the container

The next step is to check the size of the container. The size of the container is the size of the container that will be used to run the application.

Step 3: Check the time it takes to build the image

The next step is to check the time it takes to build the image. The time it takes to build the image is the time it takes to build the image that will be used to create the container.

Step 4: Check the time it takes to run the container

The next step is to check the time it takes to run the container. The time it takes to run the container is the time it takes to run the container that will be used to run the application.

Example

# Check the size of the image
docker images

# Check the size of the container
docker ps -s

# Check the time it takes to build the image
docker build -t ssibrahimbas.com/fast-dockerfile .

# Check the time it takes to run the container
docker run -p 8080:8080 ssibrahimbas.com/fast-dockerfile

My Results

In this section

Step 1: Check the size of the image

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
ssibrahimbas.com/fast-dockerfile latest 1b1b1b1b1b1b 1 second ago 9.28MB

Step 2: Check the size of the container

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                    NAMES
1b1b1b1b1b1b ssibrahimbas.com/fast-dockerfile "./app/main" 1 second ago Up 1 second

Step 3: Check the time it takes to build the image

[+] Building 0.5

Step 4: Check the time it takes to run the container

[+] Building 0.
My Results

Conclusion

In this article, we learned how to write a Dockerfile for production, how to write a Dockerfile that is safer, builds faster, has less volume and makes the first run fast, how to build the image, how to run the container and how to tell if it is fast and light.

--

--

Sami Salih İbrahimbaş
GoTurkiye

lifetime junior • software developer at monopayments