Перейти к содержимому

Как создать dockerfile ubuntu

  • автор:

Как создавать образы Docker с помощью Dockerfile

Образ Docker — это план контейнеров Docker, который содержит приложение и все необходимое для его запуска. Контейнер — это исполняемый экземпляр изображения.

В этом руководстве мы объясним, что такое Dockerfile, как его создать и как создать образ Docker с помощью Dockerfile.

Что такое Dockerfile

Dockerfile — это текстовый файл, содержащий все команды, которые пользователь может запустить в командной строке для создания образа. Он включает в себя все инструкции, необходимые Docker для создания образа.

Образы Docker состоят из серии слоев файловой системы, представляющих инструкции в файле Dockerfile образа, составляющем исполняемое программное приложение.

Файл Docker имеет следующую форму:

INSTRUCTION не чувствительна к регистру, но по соглашению для ее имен используется ЗАПИСЬ.

Ниже приведен список с кратким описанием некоторых из наиболее часто используемых инструкций Dockerfile:

  • ARG — эта инструкция позволяет вам определять переменные, которые могут быть переданы во время сборки. Вы также можете установить значение по умолчанию.
  • FROM — базовое изображение для построения нового изображения. Эта инструкция должна быть первой инструкцией без комментариев в Dockerfile. Единственное исключение из этого правила — когда вы хотите использовать переменную в аргументе FROM . В этом случае FROM может предшествовать одна или несколько инструкций ARG .
  • LABEL — используется для добавления метаданных к изображению, таких как описание, версия, автор и т. Д. Вы можете указать несколько LABEL , и каждая инструкция LABEL представляет собой пару "ключ-значение".
  • RUN — команды, указанные в этой инструкции, будут выполняться в процессе сборки. Каждая инструкция RUN создает новый слой поверх текущего изображения.
  • ДОБАВИТЬ — используется для копирования файлов и каталогов из указанного источника в указанное место назначения в образе докера. Источником могут быть локальные файлы, каталоги или URL. Если источником является локальный tar-архив, он автоматически распаковывается в образ Docker.
  • КОПИРОВАТЬ — аналогично ADD но источником может быть только локальный файл или каталог.
  • ENV — Эта инструкция позволяет вам определить переменную среды.
  • CMD — используется для указания команды, которая будет выполняться при запуске контейнера. Вы можете использовать только одну инструкцию CMD в своем Dockerfile.
  • ENTRYPOINT — аналогично CMD , эта инструкция определяет, какая команда будет выполняться при запуске контейнера.
  • WORKDIR — эта директива устанавливает текущий рабочий каталог для инструкций RUN , CMD , ENTRYPOINT , COPY и ADD .
  • ПОЛЬЗОВАТЕЛЬ — Установите имя пользователя или UID для использования при выполнении любых следующих инструкций RUN , CMD , ENTRYPOINT , COPY и ADD .
  • VOLUME — позволяет подключить каталог хост-машины к контейнеру.
  • EXPOSE — используется для указания порта, на котором контейнер прослушивает во время выполнения.

Чтобы исключить добавление файлов и каталогов в образ, создайте файл .dockerignore в контекстном каталоге. Синтаксис .dockerignore аналогичен .gitignore файла .gitignore Git.

Для получения полной справки и подробного объяснения инструкций Dockerfile см. Официальную справочную страницу Dockerfile .

Создать Dockerfile

Наиболее распространенный сценарий при создании образов Docker — извлечь существующий образ из реестра (обычно из Docker Hub) и указать изменения, которые вы хотите внести в базовый образ. Чаще всего при создании образов Docker используется базовый образ Alpine, поскольку он небольшой и оптимизирован для работы в ОЗУ.

В этом примере мы создадим образ Docker для сервера Redis. Мы будем использовать последнюю версию ubuntu 18.04 в качестве базового образа.

Сначала создайте каталог, который будет содержать Dockerfile и все необходимые файлы:

Перейдите в каталог и создайте следующий Dockerfile:

Давайте объясним значение каждой из строк в Dockerfile:

  • В строке 1 мы определяем базовое изображение.
  • Команда RUN которая начинается в строке 3 , обновит индекс apt, установит пакет «redis-server» и очистит кеш apt. Команды, используемые в инструкциях, совпадают с командами, которые вы использовали бы для установки Redis на сервере Ubuntu .
  • Инструкция EXPOSE определяет порт, который прослушивает сервер Redis.
  • В последней строке мы используем инструкцию CMD для установки команды по умолчанию, которая будет выполняться при запуске контейнера.

Сохраните файл и закройте редактор.

Создание образа

Следующим шагом будет создание образа. Для этого выполните следующую команду из каталога, в котором находится Dockerfile:

Параметр -t указывает имя изображения и, необязательно, имя пользователя и тег в формате «имя пользователя / воображаемое имя: тег».

Результат процесса сборки будет выглядеть примерно так:

Когда процесс сборки завершится, новый образ появится в списке образов:

Если вы хотите отправить образ в Docker Hub, см. « Отправка образа контейнера Docker в Docker Hub» .

Запуск контейнера

Теперь, когда образ создан, вы запускаете из него контейнер, запустив:

Параметры -d указывают Docker, что нужно запустить контейнер в автономном режиме, параметр -p 6379:6379 опубликует порт 6379 на хост-машине, а параметр —name redis указывает имя контейнера. Последний аргумент linuxize/redis — это имя изображения, которое используется для запуска контейнера.

Когда контейнер запускается, используйте следующую команду для вывода списка всех запущенных контейнеров :

Чтобы убедиться, что все работает так, как следует, используйте redis-cli для подключения к контейнеру докера:

Сервер Redis должен ответить PONG .

Выводы

В этом руководстве были рассмотрены только основы использования Dockerfiles для создания образов. Чтобы узнать больше о том, как писать файлы Docker, и рекомендуемые передовые методы, см. Рекомендации по написанию файлов Docker .

How to create Docker Images with a Dockerfile on Ubuntu 22.04 LTS

Docker is an operating system-level virtualization that is primarily aimed at developers and system administrators. Docker makes it easier to build and deploy applications in an isolated environment.

A Dockerfile is a script that contains collections of commands and instructions that are automatically executed one after another in the Docker environment to create a new Docker image.

This tutorial will show you how to create your own Docker image using a Dockerfile. We explain in detail how to create your own Docker image using a Dockerfile.

Prerequisites

For this guide, we will use Ubuntu 22.04 with 1GB of RAM, 25 GB of free disk space, and 2 CPUs. Also, we will use Ubuntu 22.04 as the base image to build the custom Docker image.

Introduction to the Dockerfile Command

A Dockerfile is a script that contains all commands for building a Docker image. The Dockerfile contains all instructions that will be used to create the Docker image with the ‘docker build’ command.

Before creating your first Dockerfile, you should be familiar with the Dockerfile instruction. Below are some Dockerfile instructions that you must know.

FROM

Set the base-image for the new image that you want to create. The FROM instruction will initialize the new build-stage and must be located at the top of the Dockerfile.

LABEL

With this instruction, you can add additional information about your Docker image, such as the version, description, maintainer, etc. The LABEL instruction is a key-value pair that allows you to add multiple labels and multi-line values.

RUN

This instruction used to execute the command during the build process of the docker image. You can install additional packages needed for your Docker images.

ADD

The ADD instruction is used to copy files, directories, or remote files from URL to your Docker images, from the ‘src’ to the absolute path ‘dest’. Also, you can set up the default ownership of your file.

ENV

The ENV instruction defines an environment variable that can be used during the build stage and can be replaced inline in many as well.

CMD

The CMD instruction defines the default command to execute when running the container. And the Dockerfile must only contain one CMD instruction, and if there is multiple CMD, the last CMD instruction will be run.

EXPOSE

This instruction exposes the container port on the specific network ports at runtime. The default protocol exposed is TCP, but you can specify whether the TCP or UDP.

ARG

The ARG instruction is used to define a variable that the user can pass at the built-time. You can use this instruction in the docker ‘build command’ during the build time using the ‘–build-arg variable=value’ option and can be pass through the Dockerfile. Also, you can use multiple ARG at the Dockerfile.

ENTRYPOINT

The ENTRYPOINT instruction is used to define the first and default command that will be executed when the container is running. Define the command to start your application with the ENTRYPOINT instruction.

WORKDIR

The WORKDIR instruction is used to define the default working directory of your Docker image. The RUN, CMD, ENTRYPOINT, and ADD instructions follow the WORKDIR instruction. You can add multiple WORKDIR instruction on your Dockerfile, and if there is doesn’t exist, it will be created automatically.

USER

The USER instruction is used to define the default user or gid when running the image. The RUN, CMD, and ENTRYPOINT follow the USER instruction in the Dockerfile.

VOLUME

The VOLUME instruction ad used to enable access/linked directory between the container and the host machine.

Now, let’s start to create the first Dockerfile.

Step 1 – Install Docker on Ubuntu 22.04

Before creating a Dockerfile, we will install the Docker to our Ubuntu 22.04 system, which is available by default in the Ubuntu repository.

Update all packages list on the Ubuntu repository and install Docker using the apt command below.

Once all installation is completed, start the Docker service and add it to the system boot.

Now check the Docker service using the command below.

The Docker service is up and running on Ubuntu 22.04.

Next, run the docker command below to ensure the installation is correct.

Below is the result you will get.

As can be seen, you get the Hello World message from Docker, and the Docker installation on Ubuntu 22.04 has been completed successfully.

Step 2 – Create Dockerfile and Other Configurations

In this step, we will show you how to build a custom Docker image for your application using the Dockerfile. We will create a new custom Docker image based on Ubuntu 22.04 image, for the PHP-FPM and Nginx services, then run the new container with a simple phpinfo script.

First, create a new project directory and create an empty Dockerfile.

Now edit the ‘Dockerfile’ script using your own editor (for this example we’re using nano).

On the top of the line, add the base-image Ubuntu 22.04 image using the FROM instruction as below.

Now add detailed information about the custom image using the LABEL instruction.

We will skip any interactive post-install step for the apt packages installation using the environment variable ‘DEBIAN_FRONTEND=noninteractive’.

Next, run the ‘apt update’ command before installing any packages.

Now install the Nginx, PHP-FPM, and supervisor packages. Once all installation is completed, remove all packages cache to reduce the size of the custom image.

Define a new environment variable that can be passed to the custom image.

Now copy the Nginx default configuration to the ‘nginx_vhost’ variable, replace the PHP configuration ‘cgi.fix_pathinfo=1’ with ‘cgi.fix_pathinfo=0’ on the php.ini config file, then add the ‘daemon off’ option to the default ‘nginx_conf’ variable.

Copy the custom supervisord configuration to the ‘supervisor_conf’ variable.

Create a new directory for PHP-FPM sock file, change the ownership of the web-root directory ‘/var/www/html’ and PHP-FPM directory ‘/run/php’ to the default user ‘www-data’.

Define the volume for the custom image so we can mount all of those directories to the host machine.

Now add the ‘start.sh’ script and define the default container command using the CMD instruction as below.

And the last, open the default HTTP and HTTPS ports on the container using the EXPOSE instruction.

Below is the complete Dockerfile script that we just created.

Next, we will create an additional configuration for Nginx, supervisord, and the start.sh script.

The ‘default’ Nginx virtualhost configuration will contain the section for the PHP-FPM. In effect, you can run the PHP script using the Custom image without any changes.

Create a new Nginx ‘default’ virtualhost configuration with your editor.

Paste the following configuration into it.

Next, we will create the ‘supervisrod.conf’ configuration, which contains both Nginx and PHP-FPM programs that will be run automatically.

Create the ‘supervisrod.conf’ file using your editor.

Paste the following configuration into it.

Now create the ‘start.sh’ script using an editor containing the supervisord command to start.

Paste the following configuration into it.

Make the ‘start.sh’ script executable.

As a result, all configuration for our custom Docker image has been created, below are all configurations we’ve created.

We’re ready to create a new custom image based on these configurations now.

Step 3 – Build New Custom and Run New Container

To create the Docker custom image, go to the project directory ‘nginx-image’ and run the ‘docker build’ command as below.

The command will download the base-image Ubuntu 22.04 and create a new custom image with the name ‘nginx-image.

Once all process is completed, check the list of available Docker image on your system using the following command.

Below is the result you will get.

As can be seen, the new custom Docker image ‘nginx-image’ has been created.

Next, we will run the new Docker container based on the ‘nginx-image’.

On your local machine, create a new directory named ‘/var/webroot’ that will be used to store all web files.

Now create a new container named test-container using the docker run command below.

Note:

  • –name test-container nginx-image = We create a new container with the name ‘test-container’, based on docker image ‘nginx-image’.
  • -p 8080:80 = test-container container running on port 8080 on the host machine.
  • -v /var/webroot:/var/www/html = /var/webroot directory on the host machine rewrite the /var/www/html directory on the container.

After that, check all running containers on your system using the following command.

Below is the result you will get.

As a result, the new container named ‘test-container’ based on the ‘nginx-image’ and expose the port 8080 is up and running.

Step 4 – Testing

To ensure that the container is running correctly, we will create a new index.html and phpinfo file on the host machine’s’/webroot’ root directory. Because the ‘/var/webroot’ directory is mounted into the container directory ‘/var/www/html’.

Create the index.html file on the ‘/webroot’ directory using the following command.

Now test access your container with the curl command on port 8080.

As a result, you will get the default index.html page we just created.

Next, create a new PHP file ‘info.php’ on the ‘/webroot’ directory to make sure that the PHP-FPM service is running.

Create the ‘info.php’ file using the following command.

Next, open your web browser and type your server IP address with port ‘8080’ followed by the path of the ‘info.php’ file.

Now you will get the phpinfo page as below.

As can be seen, the ‘test-container’ successfully loaded the PHP script.

And as a result, we’ve successfully created a new custom Docker image and run the new container based on it without any error.

Everything you need to know about Dockerfile

In this tutorial I am going to explain each and everything about a Dockerfile.

What is a Dockerfile?

A Dockerfile is just another text file. It contains a list of commands that the Docker client calls while creating an image.

The commands I am talking about here are almost similar to their equivalent Linux commands. So one no need to learn any new syntactical rules here.

Why we need Dockerfile?

The answer is simple and straightforward : “To automate the image creation process.”

Workflow around Dockerfile

The workflow will be like this:

  1. You create the Dockerfile and define the steps required to build up your image
  2. You then issue the docker build command which will build a Docker image
  3. Now you can use this image to start provisioning containers with the docker run command
  4. The Docker image you created can now be pushed to your private docker registry server to make it available for everyone within your organization.

Dockerfile creation example

Let’s start with an example to understand the Dockerfile creation in detail.

Step 1: Create a file named Dockerfile
Create a file named “Dockerfile” and edit it using any text editor of your choice. Please note that the name of the file has to be “Dockerfile” with “D” as capital and there won’t be any file extensions.

Step 2 − Start adding step by step instructions to your Dockerfile

Let’s decode the file step by step now.

  • The first line “#This is a sample Dockerfile” is a comment. Comments can be added to the Docker File with the help of the # command
  • Every Dockerfile must start with the FROM instruction. That means you need to mention a starting point. In our example, we are creating an image from the ubuntu image.
    Note: You can start FROM scratch , scratch is an explicitly empty image on the Docker store that is used to build base images like Alpine, Debian and so on.
  • The next command mentions the email id of the person who is going to maintain this image. Keyword here is MAINTAINER.
  • Next is RUN command which is used to run instructions against the image we are creating. In our example, we first update our Ubuntu system and then install the nginx server on our ubuntu image.
  • In the last command we are displaying a message to the user who is using this image.

Step 3: Build our image
Run the following command in terminal:
docker build -t rakeshrhcss/nginx-ubuntu:1.0 .

Understand the command we ran above:

  • docker build is the command to build a Docker image from a Dockerfile
  • -t option is to tag the image.
    here I am using rakeshrhcss/nginx-ubuntu:1.0 which will be basically the name of the image. As the first part put the name of the maintainer then give some human readable name nginx-ubuntu and provided a version number 1.0 .

NOTE: the . (dot) at the end of the line. You need to specify the directory where docker build should be looking for a Dockerfile. Therefore . tells docker build to look for the file in the current working directory.

Step 4: Verify the image
Docker created an image from your Dockerfile. Now you should see a new image in your image list. Run docker images ls command.

Step 5: Run a container using your image

List out the container we just ran:

So we have successfully ran the container using our own image created by Dockerfile.

Dockerfile key instructions

Lets understand what all instruction we can use within our Dockerfile.
A should be to know that there aren’t many.

FROM:
A valid Dockerfile must start with FROM
The FROM instruction initializes a new build stage and sets the Base Image for subsequent instructions. As of version 17.05, you can have more than one FROM instruction in one Dockerfile.

COPY:
The COPY instruction copies new files or directories from <src> and adds them to the filesystem of the container at the path <dest> .

Few examples —
To add all files starting with “web”:
COPY web* /mydir/

The <dest> is an absolute path, or a path relative to WORKDIR , into which the source will be copied inside the destination container.

The example below uses a relative path, and adds “test.txt” to <WORKDIR>/relativePathDir/ :

Whereas this example uses an absolute path, and adds “test.txt” to /absolutePathDir/

All new files and directories are created with a UID and GID of 0, unless the optional —chown flag specifies a given username, groupname, or UID/GID combination to request specific ownership of the copied content.

Few examples with —chown flag:

NOTE:
If <dest> does not end with a trailing slash, it will be considered a regular file and the contents of <src> will be written at <dest> .

ADD:
The ADD instruction copies new files, directories or remote file URLs from <src> and adds them to the filesystem of the image at the path <dest> .

To add all files starting with “ web ”:

COPY vs ADD
Both ADD and COPY are both used to add directories and files to your Docker image.
Recommended is to use COPY . Because ADD has many extra features compared to COPY that make ADD more unpredictable and a bit over-designed.
ADD can pull files from url sources, COPY cannot.
ADD can extract compressed files assuming it can recognize and handle the format. COPY cannot.

If you want to pull files from the web into your image I would suggest to use RUN and curl and uncompress your files with RUN and commands you would use on the command line.

ENV:
ENV is used to define environment variables.

  • You can use it to define environment variables that will be available in your container. Same will be available to use when you run a container using your image.
  • The variable you specify by ENV in the Dockerfile can be used in all subsequent instructions within the same Dockerfile itself.

RUN:
RUN will execute commands. It is the most used instruction.

RUN has 2 forms:

  • RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
  • RUN ["executable", "param1", "param2"] (exec form)

The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile .

In the shell form you can use a \ (backslash) to continue a single RUN instruction onto the next line. For example, consider these two lines:

Together they are equivalent to this single line:

To use a different shell, other than ‘/bin/sh’, use the exec form passing in the desired shell. For example:

Unlike the shell form, the exec form does not invoke a command shell.
For example, RUN [ "echo", "$HOME" ] will not do variable substitution on $HOME . If you want shell processing then either use the shell form or execute a shell directly, for example: RUN [ "sh", "-c", "echo $HOME" ] . When using the exec form and executing a shell directly, as in the case for the shell form, it is the shell that is doing the environment variable expansion, not docker.

VOLUME:
You can use the VOLUME instruction in a Dockerfile to instruct Docker that the data you store in that specific directory should be stored on the host file system not in the container file system. This implies that data stored in the volume will persist and be available also after you destroy the container.

The docker run command initializes the newly created volume with any data that exists at the specified location within the base image. For example, consider the following Dockerfile snippet:

USER:
The USER instruction sets the user name (or UID) and optionally the user group (or GID) to use when running the image and for any RUN , CMD and ENTRYPOINT instructions that follow it in the Dockerfile .

NOTE: When the user doesn’t have a primary group then the image (or the next instructions) will be run with the root group.

WORKDIR:
The WORKDIR instruction sets the working directory for any RUN , CMD , ENTRYPOINT , COPY and ADD instructions that follow it in the Dockerfile . If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.

EXPOSE:
The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified.

An important instruction to inform your users about the ports your application is listening on. EXPOSE will not publish the port, you need to use docker run -p. to do that when you start the container.

ONBUILD:
You can specify instructions with ONBUILD that will be executed when your image is used as the base image of another Dockerfile. 🙂

This is useful when you want to create a generic base image to be used in different variations by many Dockerfiles, or in many projects or by many parties.

So you do not need to add the specific stuff immediately, like you don’t need to copy the source code or config files in the base image. How could you even do that, when these things will be available only later?

So what you do instead is to add ONBUILD instructions. So you can do something like this:

ONBUILD instructions will be executed right after the FROM instruction in the downstream Dockerfile.

CMD and ENTRYPOINT:
Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. There are few rules that describe their co-operation.

  • Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
  • ENTRYPOINT should be defined when using the container as an executable.
  • CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container.
  • CMD will be overridden when running the container with alternative arguments.

With CMD instruction you can specify what component is to be run by your image with arguments in the following form: CMD [“executable”, “param1”, “param2”…] .

You can override CMD when you’re starting up your container by specifying your command after the image name like this: $ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG. ] .

You can only specify one CMD in a Dockerfile (you can specify more than one, but only the last one will be used).

It is good practice to specify a CMD even if you are developing a generic container, in this case an interactive shell is a good CMD entry. So you do CMD ["python"] or CMD [“php”, “-a”] to give your users something to work with.

So what’s the deal with ENTRYPOINT ? When you specify an entry point, your image will work a bit differently. You use ENTRYPOINT as the main executable of your image. In this case whatever you specify in CMD will be added to ENTRYPOINT as parameters.

This way you can build Docker images that mimic the behavior of the main executable you specify in ENTRYPOINT .

ARG:
The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the —build-arg <varname>=<value> flag. If a user specifies a build argument that was not defined in the Dockerfile, the build outputs a warning.

A Dockerfile may include one or more ARG instructions.

It’s bit lengthy article but would help you a lot in understanding the core concepts of a Dockerfile.

Hope you like the article. Please let me know your feedback in the response section.

Изучаем Docker, часть 3: файлы Dockerfile

В переводе третьей части серии материалов, посвящённых Docker, мы продолжим вдохновляться выпечкой, а именно — бубликами. Нашей сегодняшней основной темой будет работа с файлами Dockerfile. Мы разберём инструкции, которые используются в этих файлах.

Образы Docker

Вспомните о том, что контейнер Docker — это образ Docker, вызванный к жизни. Это — самодостаточная операционная система, в которой имеется только самое необходимое и код приложения.

Образы Docker являются результатом процесса их сборки, а контейнеры Docker — это выполняющиеся образы. В самом сердце Docker находятся файлы Dockerfile. Подобные файлы сообщают Docker о том, как собирать образы, на основе которых создаются контейнеры.

Каждому образу Docker соответствует файл, который называется Dockerfile. Его имя записывается именно так — без расширения. При запуске команды docker build для создания нового образа подразумевается, что Dockerfile находится в текущей рабочей директории. Если этот файл находится в каком-то другом месте, его расположение можно указать с использованием флага -f .

Контейнеры, как мы выяснили в первом материале этой серии, состоят из слоёв. Каждый слой, кроме последнего, находящегося поверх всех остальных, предназначен только для чтения. Dockerfile сообщает системе Docker о том, какие слои и в каком порядке надо добавить в образ.

Каждый слой, на самом деле, это всего лишь файл, который описывает изменение состояния образа в сравнении с тем состоянием, в котором он пребывал после добавления предыдущего слоя. В Unix, кстати, практически всё что угодно — это файл.

Базовый образ — это то, что является исходным слоем (или слоями) создаваемого образа. Базовый образ ещё называют родительским образом.

Базовый образ — это то, с чего начинается образ Docker

Когда образ загружается из удалённого репозитория на локальный компьютер, то физически скачиваются лишь слои, которых на этом компьютере нет. Docker стремится экономить пространство и время путём повторного использования существующих слоёв.

Файлы Dockerfile

В файлах Dockerfile содержатся инструкции по созданию образа. С них, набранных заглавными буквами, начинаются строки этого файла. После инструкций идут их аргументы. Инструкции, при сборке образа, обрабатываются сверху вниз. Вот как это выглядит:

Слои в итоговом образе создают только инструкции FROM , RUN , COPY , и ADD . Другие инструкции что-то настраивают, описывают метаданные, или сообщают Docker о том, что во время выполнения контейнера нужно что-то сделать, например — открыть какой-то порт или выполнить какую-то команду.

Здесь мы исходим из предположения, в соответствии с которым используется образ Docker, основанный на Unix-подобной ОС. Конечно, тут можно воспользоваться и образом, основанным на Windows, но использование Windows — это менее распространённая практика, работать с такими образами сложнее. В результате, если у вас есть такая возможность, пользуйтесь Unix.

Для начала приведём список инструкций Dockerfile с краткими комментариями.

Дюжина инструкций Dockerfile

  1. FROM — задаёт базовый (родительский) образ.
  2. LABEL — описывает метаданные. Например — сведения о том, кто создал и поддерживает образ.
  3. ENV — устанавливает постоянные переменные среды.
  4. RUN — выполняет команду и создаёт слой образа. Используется для установки в контейнер пакетов.
  5. COPY — копирует в контейнер файлы и папки.
  6. ADD — копирует файлы и папки в контейнер, может распаковывать локальные .tar-файлы.
  7. CMD — описывает команду с аргументами, которую нужно выполнить когда контейнер будет запущен. Аргументы могут быть переопределены при запуске контейнера. В файле может присутствовать лишь одна инструкция CMD .
  8. WORKDIR — задаёт рабочую директорию для следующей инструкции.
  9. ARG — задаёт переменные для передачи Docker во время сборки образа.
  10. ENTRYPOINT — предоставляет команду с аргументами для вызова во время выполнения контейнера. Аргументы не переопределяются.
  11. EXPOSE — указывает на необходимость открыть порт.
  12. VOLUME — создаёт точку монтирования для работы с постоянным хранилищем.

Инструкции и примеры их использования

▍Простой Dockerfile

Dockerfile может быть чрезвычайно простым и коротким. Например — таким:

▍Инструкция FROM

Файл Dockerfile должен начинаться с инструкции FROM , или с инструкции ARG , за которой идёт инструкция FROM .

Ключевое слово FROM сообщает Docker о том, чтобы при сборке образа использовался бы базовый образ, который соответствует предоставленному имени и тегу. Базовый образ, кроме того, ещё называют родительским образом.

В этом примере базовый образ хранится в репозитории ubuntu. Ubuntu — это название официального репозитория Docker, предоставляющего базовую версию популярной ОС семейства Linux, которая называется Ubuntu.

Обратите внимание на то, что рассматриваемый Dockerfile включает в себя тег 18.04 , уточняющий то, какой именно базовый образ нам нужен. Именно этот образ и будет загружен при сборке нашего образа. Если тег в инструкцию не включён, тогда Docker исходит из предположения о том, что требуется самый свежий образ из репозитория. Для того чтобы яснее выразить свои намерения, автору Dockerfile рекомендуется указывать то, какой именно образ ему нужен.

Когда вышеописанный Dockerfile используется на локальной машине для сборки образа в первый раз, Docker загрузит слои, определяемые образом ubuntu . Их можно представить наложенными друг на друга. Каждый следующий слой представляет собой файл, описывающий отличия образа в сравнении с тем его состоянием, в котором он был после добавления в него предыдущего слоя.

При создании контейнера слой, в который можно вносить изменения, добавляется поверх всех остальных слоёв. Данные, находящиеся в остальных слоях, можно только читать.

Структура контейнера (взято из документации)

Docker, ради эффективности, использует стратегию копирования при записи. Если слой в образе существует на предыдущем уровне и какому-то слою нужно произвести чтение данных из него, Docker использует существующий файл. При этом ничего загружать не нужно.

Когда образ выполняется, если слой нужно модифицировать средствами контейнера, то соответствующий файл копируется в самый верхний, изменяемый слой. Для того чтобы узнать подробности о стратегии копирования при записи, взгляните на этот материал из документации Docker.

Продолжим рассмотрение инструкций, которые используются в Dockerfile, приведя пример такого файла с более сложной структурой.

▍Более сложный Dockerfile

Хотя файл Dockerfile, который мы только что рассмотрели, получился аккуратным и понятным, он устроен слишком просто, в нём используется всего одна инструкция. Кроме того, там нет инструкций, вызываемых во время выполнения контейнера. Взглянем на ещё один файл, который собирает маленький образ. В нём имеются механизмы, определяющие команды, вызываемые во время выполнения контейнера.

Возможно, на первый взгляд этот файл может показаться довольно сложным. Поэтому давайте с ним разберёмся.

Базой этого образа является официальный образ Python с тегом 3.7.2-alpine3.8. Проанализировав этот код можно увидеть, что данный базовый образ включает в себя Linux, Python, и, по большому счёту, этим его состав и ограничивается. Образы ОС Alpine весьма популярны в мире Docker. Дело в том, что они отличаются маленькими размерами, высокой скоростью работы и безопасностью. Однако образы Alpine не отличаются широкими возможностями, характерными для обычных операционных систем. Поэтому для того, чтобы собрать на основе такого образа что-то полезное, создателю образа нужно установить в него необходимые ему пакеты.

▍Инструкция LABEL

Инструкция LABEL (метка) позволяет добавлять в образ метаданные. В случае с рассматриваемым сейчас файлом, она включает в себя контактные сведения создателя образа. Объявление меток не замедляет процесс сборки образа и не увеличивает его размер. Они лишь содержат в себе полезную информацию об образе Docker, поэтому их рекомендуется включать в файл. Подробности о работе с метаданными в Dockerfile можно прочитать здесь.

▍Инструкция ENV

Окружающая среда

Инструкция ENV позволяет задавать постоянные переменные среды, которые будут доступны в контейнере во время его выполнения. В предыдущем примере после создания контейнера можно пользоваться переменной ADMIN .

Инструкция ENV хорошо подходит для задания констант. Если вы используете некое значение в Dockerfile несколько раз, скажем, при описании команд, выполняющихся в контейнере, и подозреваете, что, возможно, вам когда-нибудь придётся сменить его на другое, его имеет смысл записать в подобную константу.

Надо отметить, что в файлах Dockerfile часто существуют разные способы решения одних и тех же задач. Что именно использовать — это вопрос, на решение которого влияет стремление к соблюдению принятых в среде Docker методов работы, к обеспечению прозрачности решения и его высокой производительности. Например, инструкции RUN , CMD и ENTRYPOINT служат разным целям, но все они используются для выполнения команд.

▍Инструкция RUN

Инструкция RUN

Инструкция RUN позволяет создать слой во время сборки образа. После её выполнения в образ добавляется новый слой, его состояние фиксируется. Инструкция RUN часто используется для установки в образы дополнительных пакетов. В предыдущем примере инструкция RUN apk update && apk upgrade сообщает Docker о том, что системе нужно обновить пакеты из базового образа. Вслед за этими двумя командами идёт команда && apk add bash , указывающая на то, что в образ нужно установить bash.

То, что в командах выглядит как apk — это сокращение от Alpine Linux package manager (менеджер пакетов Alpine Linux). Если вы используете базовый образ какой-то другой ОС семейства Linux, тогда вам, например, при использовании Ubuntu, для установки пакетов может понадобиться команда вида RUN apt-get . Позже мы поговорим о других способах установки пакетов.

Инструкция RUN и схожие с ней инструкции — такие, как CMD и ENTRYPOINT , могут быть использованы либо в exec-форме, либо в shell-форме. Exec-форма использует синтаксис, напоминающий описание JSON-массива. Например, это может выглядеть так: RUN [«my_executable», «my_first_param1», «my_second_param2»] .

В предыдущем примере мы использовали shell-форму инструкции RUN в таком виде: RUN apk update && apk upgrade && apk add bash .

Позже в нашем Dockerfile использована exec-форма инструкции RUN , в виде RUN [«mkdir», «/a_directory»] для создания директории. При этом, используя инструкцию в такой форме, нужно помнить о необходимости оформления строк с помощью двойных кавычек, как это принято в формате JSON.

▍Инструкция COPY

Инструкция COPY

Инструкция COPY представлена в нашем файле так: COPY . ./app . Она сообщает Docker о том, что нужно взять файлы и папки из локального контекста сборки и добавить их в текущую рабочую директорию образа. Если целевая директория не существует, эта инструкция её создаст.

▍Инструкция ADD

Инструкция ADD позволяет решать те же задачи, что и COPY , но с ней связана ещё пара вариантов использования. Так, с помощью этой инструкции можно добавлять в контейнер файлы, загруженные из удалённых источников, а также распаковывать локальные .tar-файлы.

В этом примере инструкция ADD была использована для копирования файла, доступного по URL, в директорию контейнера my_app_directory . Надо отметить, однако, что документация Docker не рекомендует использование подобных файлов, полученных по URL, так как удалить их нельзя, и так как они увеличивают размер образа.

Кроме того, документация предлагает везде, где это возможно, вместо инструкции ADD использовать инструкцию COPY для того, чтобы сделать файлы Dockerfile понятнее. Полагаю, команде разработчиков Docker стоило бы объединить ADD и COPY в одну инструкцию для того, чтобы тем, кто создаёт образы, не приходилось бы помнить слишком много инструкций.

Обратите внимание на то, что инструкция ADD содержит символ разрыва строки — \ . Такие символы используются для улучшения читабельности длинных команд путём разбиения их на несколько строк.

▍Инструкция CMD

Инструкция CMD

Инструкция CMD предоставляет Docker команду, которую нужно выполнить при запуске контейнера. Результаты выполнения этой команды не добавляются в образ во время его сборки. В нашем примере с помощью этой команды запускается скрипт my_script.py во время выполнения контейнера.

Вот ещё кое-что, что нужно знать об инструкции CMD :

  • В одном файле Dockerfile может присутствовать лишь одна инструкция CMD . Если в файле есть несколько таких инструкций, система проигнорирует все кроме последней.
  • Инструкция CMD может иметь exec-форму. Если в эту инструкцию не входит упоминание исполняемого файла, тогда в файле должна присутствовать инструкция ENTRYPOINT . В таком случае обе эти инструкции должны быть представлены в формате JSON .
  • Аргументы командной строки, передаваемые docker run , переопределяют аргументы, предоставленные инструкции CMD в Dockerfile.

▍Ещё более сложный Dockerfile

Рассмотрим ещё один файл Dockerfile, в котором будут использованы некоторые новые команды.

В этом примере, кроме прочего, вы можете видеть комментарии, которые начинаются с символа # .
Одно из основных действий, выполняемых средствами Dockerfile — это установка пакетов. Как уже было сказано, существуют различные способы установки пакетов с помощью инструкции RUN .

Пакеты в образ Alpine Docker можно устанавливать с помощью apk . Для этого, как мы уже говорили, применяется команда вида RUN apk update && apk upgrade && apk add bash .

Кроме того, пакеты Python в образ можно устанавливать с помощью pip, wheel и conda. Если речь идёт не о Python, а о других языках программирования, то при подготовке соответствующих образов могут использоваться и другие менеджеры пакетов.

При этом для того, чтобы установка была бы возможной, нижележащий слой должен предоставить слою, в который выполняется установка пакетов, подходящий менеджер пакетов. Поэтому если вы столкнулись с проблемами при установке пакетов, убедитесь в том, что менеджер пакетов установлен до того, как вы попытаетесь им воспользоваться.

Например, инструкцию RUN в Dockerfile можно использовать для установки списка пакетов с помощью pip . Если вы так поступаете — объедините все команды в одну инструкцию и разделите её символами разрыва строки с помощью символа \ . Благодаря такому подходу файлы будут выглядеть аккуратно и это приведёт к добавлению в образ меньшего количества слоёв, чем было бы добавлено при использовании нескольких инструкций RUN .

Кроме того, для установки нескольких пакетов можно поступить и по-другому. Их можно перечислить в файле и передать менеджеру пакетов этот файл с помощью RUN . Обычно таким файлам дают имя requirements.txt .

▍Инструкция WORKDIR

Рабочие директории

Инструкция WORKDIR позволяет изменить рабочую директорию контейнера. С этой директорией работают инструкции COPY , ADD , RUN , CMD и ENTRYPOINT , идущие за WORKDIR . Вот некоторые особенности, касающиеся этой инструкции:

  • Лучше устанавливать с помощью WORKDIR абсолютные пути к папкам, а не перемещаться по файловой системе с помощью команд cd в Dockerfile.
  • Инструкция WORKDIR автоматически создаёт директорию в том случае, если она не существует.
  • Можно использовать несколько инструкций WORKDIR . Если таким инструкциям предоставляются относительные пути, то каждая из них меняет текущую рабочую директорию.

▍Инструкция ARG

Инструкция ARG позволяет задать переменную, значение которой можно передать из командной строки в образ во время его сборки. Значение для переменной по умолчанию можно представить в Dockerfile. Например: ARG my_var=my_default_value .

В отличие от ENV -переменных, ARG -переменные недоступны во время выполнения контейнера. Однако ARG -переменные можно использовать для задания значений по умолчанию для ENV -переменных из командной строки в процессе сборки образа. А ENV -переменные уже будут доступны в контейнере во время его выполнения. Подробности о такой методике работы с переменными можно почитать здесь.

▍Инструкция ENTRYPOINT

Пункт перехода в какое-то место

Инструкция ENTRYPOINT позволяет задавать команду с аргументами, которая должна выполняться при запуске контейнера. Она похожа на команду CMD , но параметры, задаваемые в ENTRYPOINT , не перезаписываются в том случае, если контейнер запускают с параметрами командной строки.

Вместо этого аргументы командной строки, передаваемые в конструкции вида docker run my_image_name , добавляются к аргументам, задаваемым инструкцией ENTRYPOINT . Например, после выполнения команды вида docker run my_image bash аргумент bash добавится в конец списка аргументов, заданных с помощью ENTRYPOINT . Готовя Dockerfile, не забудьте об инструкции CMD или ENTRYPOINT .

В документации к Docker есть несколько рекомендаций, касающихся того, какую инструкцию, CMD или ENTRYPOINT , стоит выбрать в качестве инструмента для выполнения команд при запуске контейнера:

  • Если при каждом запуске контейнера нужно выполнять одну и ту же команду — используйте ENTRYPOINT .
  • Если контейнер будет использоваться в роли приложения — используйте ENTRYPOINT .
  • Если вы знаете, что при запуске контейнера вам понадобится передавать ему аргументы, которые могут перезаписывать аргументы, указанные в Dockerfile, используйте CMD .

Документация Docker рекомендует использовать exec-форму ENTRYPOINT : ENTRYPOINT [«executable», «param1», «param2»] .

▍Инструкция EXPOSE

Инструкция EXPOSE

Инструкция EXPOSE указывает на то, какие порты планируется открыть для того, чтобы через них можно было бы связаться с работающим контейнером. Эта инструкция не открывает порты. Она, скорее, играет роль документации к образу, средством общения того, кто собирает образ, и того, кто запускает контейнер.

Для того чтобы открыть порт (или порты) и настроить перенаправление портов, нужно выполнить команду docker run с ключом -p . Если использовать ключ в виде -P (с заглавной буквой P ), то открыты будут все порты, указанные в инструкции EXPOSE .

▍Инструкция VOLUME

Инструкция VOLUME

Инструкция VOLUME позволяет указать место, которое контейнер будет использовать для постоянного хранения файлов и для работы с такими файлами. Об этом мы ещё поговорим.

Итоги

Теперь вы знаете дюжину инструкций, применяемых при создании образов с помощью Dockerfile. Этим список таких инструкций не исчерпывается. В частности, мы не рассмотрели здесь такие инструкции, как USER , ONBUILD , STOPSIGNAL , SHELL и HEALTHCHECK . Вот краткий справочник по инструкциям Dockerfile.

Вероятно, файлы Dockerfile — это ключевой компонент экосистемы Docker, работать с которым нужно научиться всем, кто хочет уверенно чувствовать себя в этой среде. Мы ещё вернёмся к разговору о них в следующий раз, когда будем обсуждать способы уменьшения размеров образов.

Уважаемые читатели! Если вы пользуетесь Docker на практике, просим рассказать о том, как вы пишете Docker-файлы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Капельница от запоя — облегчение за 15–20 минут