Dockerfile Ubuntu: A Beginner’s Guide for Developers

目次

1. Introduction

What are Docker and Dockerfile?

In recent years, Docker has rapidly gained popularity as a means to streamline the setup of development environments and the deployment of applications. Docker has the unique ability to package an application and its dependencies into a single “container,” which can then be run in the same environment anywhere.

To build this Docker container, a blueprint called “Dockerfile” is necessary. A Dockerfile is a text file that specifies the base OS image, software to be installed, environment variable settings, and more. Developers can use this file to automatically build customized environments.

Reasons for Choosing Ubuntu as the Base

When creating a Dockerfile, the first step is to specify the base OS image. Among the many options, Ubuntu is particularly popular. Ubuntu is a Debian-based Linux distribution known for its ease of use and the flexibility to build diverse environments thanks to its extensive package repository.

A Dockerfile based on Ubuntu offers the following advantages:

  • Abundant official and community documentation is available, resulting in a lower learning curve.
  • Many packages and tools can be easily installed using APT (Advanced Package Tool).
  • Lightweight minimal images (such as ubuntu:20.04, ubuntu:24.04) are officially provided.

Purpose and Target Audience of This Article

In this article, we will focus on the keyword “Dockerfile Ubuntu” and provide an easy-to-understand explanation for beginners on how to create Ubuntu-based Dockerfiles.

Specifically, we will comprehensively cover everything from the basic structure of a Dockerfile to the steps for actually building an Ubuntu environment, examples of installing application environments like Python, and common errors with their solutions.

This article is recommended for:

  • Those who want to build an environment using Dockerfile for the first time.
  • Those who want to create a reproducible development environment on Ubuntu.
  • Those who want to deepen their knowledge, including how to troubleshoot issues.

2. Basic Structure of a Dockerfile

What is a Dockerfile? Understanding Its Role

A Dockerfile is like a recipe for creating a Docker image. Specifically, it’s a text file that describes which base OS to use, what software to install, and what configurations to apply.

By executing the docker build command using this file, you can easily build highly reproducible development and application execution environments.

Benefits of using Dockerfile:

  • Automation of environment setup (no need to reproduce manual steps).
  • Eliminates environment inconsistencies when developing with multiple team members.
  • Easy to integrate into CI/CD pipelines.

Commonly Used Basic Instructions (Directives) in Dockerfile

A Dockerfile contains several instructions (directives), with the following being the most representative. We will combine these appropriately to create an Ubuntu-based Dockerfile.

InstructionDescription
FROMSpecifies the base Docker image. Example: FROM ubuntu:24.04
RUNExecutes shell commands. Used for package installation, etc.
COPYCopies local files into the image.
ADDSimilar to COPY, but also allows fetching from URLs and extracting archives.
WORKDIRSets the working directory.
ENVSets environment variables.
CMDDefines the command to be executed when the container starts (can be overridden).
ENTRYPOINTSimilar to CMD, but defines a command that is always executed.

Minimal Example of an Ubuntu-Based Dockerfile

Below is a very basic example of a Dockerfile based on Ubuntu.

FROM ubuntu:24.04

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

CMD ["/bin/bash"]

This Dockerfile is configured to use Ubuntu 24.04 as the base, install two utilities (curl and vim), and finally start the bash shell.

About Selecting Ubuntu Tags

Ubuntu Docker images are available on the official Docker Hub repository. While specifying ubuntu:latest will use the newest version, it is recommended to explicitly pin a version.

For example:

  • ubuntu:22.04 (LTS: Long Term Support version, emphasizes stability)
  • ubuntu:24.04 (Latest LTS candidate, emphasizes features)

Consider whether to prioritize stability or new features depending on your purpose.

3. Practice: Creating an Ubuntu-Based Dockerfile

Installing Necessary Packages for the Ubuntu Environment

When building an Ubuntu environment using Dockerfile, you will often need to install additional packages. For example, the following utilities are commonly used to set up a development environment:

  • curl: For fetching files and checking APIs.
  • vim: A simple text editor.
  • git: A version control tool.
  • build-essential: A collection of basic tools necessary for building C/C++ programs.

To install these in a Dockerfile, use the RUN instruction.

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y
    curl
    vim
    git
    build-essential

By running apt-get update first, you ensure that the latest package lists are obtained before installation.

Setting Up Non-Interactive Installation

In Ubuntu, apt-get install may require user input, but interactive operations are not possible during the Docker build process. Therefore, it is recommended to set the environment variable as follows to perform the installation in non-interactive mode.

ENV DEBIAN_FRONTEND=noninteractive

This will skip prompts such as “Regional Settings” that appear during package configuration, allowing the installation to proceed smoothly.

Reducing Image Size by Removing Unnecessary Cache

When using APT, downloaded temporary files (cache) can remain in the image, making the final Docker image larger. You can reduce the image size by deleting this cache as follows:

RUN apt-get update && apt-get install -y
    curl
    vim
    && rm -rf /var/lib/apt/lists/*

By combining multiple commands into a single RUN statement like this, you can also prevent the creation of unnecessary layers.

Best Practices: Organizing Your Dockerfile

In actual development environments, the following best practices for writing Dockerfiles are recommended:

  • Combine RUN instructions as much as possible to reduce the number of layers.
  • Explicitly define versions and configurations using ENV.
  • Use comments to clearly state the purpose of each operation.
  • Use rm and --no-install-recommends to avoid leaving unnecessary files.

Example:

RUN apt-get update && apt-get install -y --no-install-recommends
    curl
    git
    && rm -rf /var/lib/apt/lists/*

By doing this, you can build a more lightweight and maintainable Dockerfile.

4. Building and Verifying the Docker Image

Building a Docker Image from a Dockerfile

Once you have written your Dockerfile, the next step is to build the Docker image. This is done using the docker build command. Execute the following command in the directory where your Dockerfile is located:

docker build -t my-ubuntu-image .
  • The -t option is used to give the image a name (tag). In this example, we are naming it my-ubuntu-image.
  • The . refers to the current directory where the Dockerfile is located.

When you run this command, Docker will sequentially read the instructions in the Dockerfile and build a new image accordingly.

Verifying the Built Docker Image

After the image creation is complete, you can verify it with the following command:

docker images

This will display a list of Docker images that exist locally, and you can check the following information:

  • REPOSITORY (image name)
  • TAG (tag)
  • IMAGE ID (unique identifier)
  • CREATED (creation date and time)
  • SIZE (size)

Example:

REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
my-ubuntu-image    latest    abcd1234abcd    5 minutes ago   189MB

This confirms that the image you created has been successfully registered.

Starting a Docker Container and Verifying Operation

To verify that the created image functions correctly, let’s start a Docker container. Use the following command:

docker run -it my-ubuntu-image
  • Specifying the -it option allows you to start a terminal in interactive mode.
  • If it starts successfully, a bash prompt within the container will appear, and you will bein a state as if you have logged into an Ubuntu environment.

Inside the container, you can execute commands like the following to check if the installed tools are working correctly:

curl --version
vim --version

If there are no issues, the Dockerfile has been written successfully.

Cleaning Up Unnecessary Images and Containers

As you repeat builds and experiments, unnecessary Docker images and containers may accumulate locally. It is recommended to periodically clean them up using commands like the following:

  • Deleting stopped containers:
docker container prune
  • Deleting unused images:
docker image prune
  • Deleting all unused data (Caution!):
docker system prune

These operations help to save disk space and prevent issues.

5. Application: Building a Python Environment

Making Python Usable in an Ubuntu-Based Dockerfile

By adding a Python execution environment when building an Ubuntu environment using Dockerfile, you can support a wide range of uses such as development, testing, and machine learning. While Ubuntu may have Python pre-installed, it is common practice to explicitly build it yourself from the perspective of version and package management.

How to Install Python Using apt

The simplest way is to install Python using APT packages. Here’s an example:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y
    python3
    python3-pip
    && rm -rf /var/lib/apt/lists/*

With this method, you can use the stable version of Python installed on the system (usually Python 3.10 or 3.12, etc.). In addition, you can add Python packages using the pip command.

Managing Python Versions with pyenv

If you want to use a specific Python version or switch between multiple versions, using pyenv is convenient.

Below is an example of using pyenv to install Python 3.11.6 in a Dockerfile:

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y
    git
    curl
    make
    build-essential
    libssl-dev
    zlib1g-dev
    libbz2-dev
    libreadline-dev
    libsqlite3-dev
    wget
    llvm
    libncurses5-dev
    libncursesw5-dev
    xz-utils
    tk-dev
    libffi-dev
    liblzma-dev
    && rm -rf /var/lib/apt/lists/*

# Install pyenv
RUN git clone [https://github.com/pyenv/pyenv.git](https://github.com/pyenv/pyenv.git) ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# Install a specific Python version
RUN pyenv install 3.11.6 && pyenv global 3.11.6

This allows you to build and manage your Python environment more flexibly.

Package Management Using requirements.txt

In actual projects, you will often need multiple Python libraries. requirements.txt is used to manage these.

First, prepare a requirements.txt file in the root directory of your project:

flask==2.3.2
requests>=2.25.1
pandas

Next, describe it in the Dockerfile as follows:

COPY requirements.txt /app/requirements.txt
WORKDIR /app

RUN pip install --no-cache-dir -r requirements.txt

This allows you to install the necessary libraries all at once, increasing the reproducibility of your development environment.

Best Practices

  • When using Python, building a virtual environment with virtualenv or venv can help prevent dependency conflicts.
  • You can reduce the size of your Docker image by deleting the cache (--no-cache-dir).
  • Installing the latest version of pip with pip install --upgrade pip before installing Python packages can prevent errors.

6. Common Issues and Solutions

Permission Errors

Example:

Permission denied

This occurs when the copied file does not have execute permissions or when the file owner/executing user is not appropriate.

Solutions:

  • Make the file executable:
  RUN chmod +x script.sh
  • Change the user if necessary:
  RUN chown root:root /path/to/file

Package Not Found or Cannot Be Installed

Example:

E: Unable to locate package xxx

This error occurs when apt-get update has not been run or when the specified package name is incorrect.

Solutions:

  • Always write apt-get update before install:
  RUN apt-get update && apt-get install -y curl
  • Check the package name for typos and ensure it is correct.

Network-Related Errors

Example:

Temporary failure resolving 'deb.debian.org'

This type of error occurs when DNS resolution fails during the build process.

Solutions:

  • Restarting the Docker daemon may resolve the issue:
  sudo systemctl restart docker
  • Review the Docker DNS settings (add DNS specifications to /etc/docker/daemon.json):
  {
    "dns": ["8.8.8.8", "8.8.4.4"]
  }

Build Remains in an Old State Due to Cache Effects

Docker uses a layer-by-layer cache for speed. As a result, even if you modify the Dockerfile, it may not build as intended because cached layers are being reused.

Solution:

  • Rebuild without using the cache:
  docker build --no-cache -t my-image .

Startup Command in Container Fails to Execute or Exits Immediately

Causes:

  • The command specified in CMD or ENTRYPOINT is encountering an error.
  • Even if you specify ["/bin/bash"] in CMD, it will exit immediately if not run interactively.

Solutions:

  • Start the container for debugging and check:
  docker run -it my-image /bin/bash
  • Understand the difference between CMD and ENTRYPOINT and use them appropriately for your purpose.

By experiencing these issues, your Dockerfile design skills will definitely improve. When you encounter a problem, calmly read the error message and carefully trace which layer or instruction is the cause.

7. Conclusion

Reconfirming Key Points for Creating Ubuntu-Based Dockerfiles

In this article, we have explained step-by-step from basic to applied methods on how to build an Ubuntu environment using Dockerfile. Let’s reiterate the important points here.

  • Understanding the basic structure of a Dockerfile is the first step.
    You can automate environment setup by combining instructions such as FROM, RUN, CMD, and ENV.
  • Ubuntu is a stable and highly flexible base image.
    Its rich package repository, large user base, and the availability of LTS versions make it suitable as a foundation for development environments.
  • You can install necessary tools and libraries through practical package management.
    Knowing how to use apt-get, remove cache, and perform non-interactive installations are key.
  • Building practical environments like Python is also possible with Dockerfile.
    Tools like pyenv, pip, and requirements.txt enable you to create highly reproducible development environments.
  • Troubleshooting skills directly lead to stable operation.
    Understanding common pitfalls such as permissions, network issues, and build cache can significantly improve development efficiency.

Next Steps for Learning Dockerfile

Being able to handle Dockerfiles allows you to support a wide range of uses, not only in development but also in testing and deploying to production environments. For future learning, it would be beneficial to move on to the following topics:

  • Managing multi-container configurations using Docker Compose.
  • Integration with CI/CD tools (GitHub Actions, GitLab CI, etc.).
  • Interoperation with container orchestration tools such as Kubernetes.

8. FAQ (Frequently Asked Questions)

Q1. Which version of Ubuntu should I choose in my Dockerfile?

A1. Basically, if you prioritize stability and long-term support, it is common to choose an LTS (Long Term Support) version. For example, ubuntu:22.04 and ubuntu:20.04 are used in many development environments and can be used with confidence due to their 5-year support period.

On the other hand, if you want to use the latest packages and language versions, you can choose a newer release like ubuntu:24.04, but we recommend testing it beforehand.

Q2. Why do I get “Package not found” when using apt-get install?

A2. The most common reason is that you have not run apt-get update beforehand. If you try to install without updating the package list, you will get an error because the corresponding package cannot be found in the outdated list.

Correct usage example:

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

Also, be careful about typos in package names and deprecated package names (e.g., python3 instead of python).

Q3. How do I set environment variables in a Dockerfile?

A3. You set environment variables using the ENV instruction. This environment variable will be valid during both the build and container runtime.

Example:

ENV DEBIAN_FRONTEND=noninteractive

This is a typical setting used to suppress interactive prompts during APT installation. It is also used to set application configurations and API keys within the Dockerfile.

Q4. What is the difference between CMD and ENTRYPOINT in a Dockerfile?

A4. Both specify commands to be executed when the container starts, but there are differences in their usage and behavior.

ItemCMDENTRYPOINT
OverridableCan be overridden by the docker run commandBasically not overridden (treated as arguments)
UsageSets the default execution commandDefines a command that should always be executed

Example:

CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]

In the latter case, you can pass the CMD as an argument in the form of docker run my-image another_script.py.

Q5. I edited my Dockerfile, but the changes are not reflected. Why?

A5. Docker uses cache during the build process, so even if you make small changes to the Dockerfile, cached layers may still be used.

Solution:

docker build --no-cache -t my-image .

This will perform a new build without using the cache, and all changes will be reflected.

年収訴求