Добавить файл в docker

Обновлено: 07.07.2024

В предыдущей части данного руководства мы увидели, как можно сохранить изменения в контейнере в новый образ. Такой способ подходит, если количество изменений относительно невелико – вводить все команды вручную каждый раз может быть затруднительно. Для упрощения процесса сборки можно воспользоваться Dockerfile. Это специальный скрипт, в котором содержатся команды и инструкции, которые будут в заданной последовательности выполнены для сборки нового образа Docker.
В данном руководстве мы рассмотрим создание собственного образа Docker при помощи Dockerfile. Он будет подробно разобран, чтобы в дальнейшем вы легко смогли создать свой собственный скрипт.

Обзор команд Dockerfile

На первый взгляд команды CMD и ENTRYPOINT кажутся одинаковыми. Они выполняют команду при запуске контейнера. Но все таки между ними есть разница. Мы не будем вдаваться в тонкости, запомните только то что если вы укажете CMD то докер выполнит эту команду, используя стандартную команду ENTRYPOINT, которая является /bin/sh -c. И эту команду вы сможете переопределить при запуске контейнера Если вы укажете ENTRYPOINT то при запуске контейнера переопределить команду вы уже не сможете.

Создание Dockerfile

На данном этапе мы создадим для Dockerfile новую директорию и определим, что мы хотим сделать при помощи Dockerfile.
Создайте новую директорию и пустой файл в ней

Затем определим, какой образ требуется создать. В данном руководстве мы установим Nginx и PHP-FPM7, используя образ Ubuntu 18.04. Кроме того, нам потребуется Supervisord, чтобы запустить Nginx и PHP-FPM 7 одной командой.
Откройте Dockerfile в любом текстовом редакторе, например vim:

В начале файла добавьте строку с указанием базового образа, который мы будем использовать (Ubuntu 18.04):

Теперь установим приложения, который требуются для нашего образа. При помощи apt можно установить Nginx, PHP-FPM и Supervisord из репозитория Ubuntu. Добавьте соответствующую команду RUN:

После установки приложений их нужно настроить. Мы настроим Nginx для работы с PHP путем изменения конфигурации виртуального хоста по умолчанию. Можно отредактировать существующий файл конфигурации командой sed или заменить его новым файлом при помощи команды Dockerfile COPY.

Теперь настроим Supervisord для Nginx and PHP-FPM, точно так же заменив файл конфигурации по умолчанию новым файлом, используя команду COPY.

Создадим новую директорию для sock-файла php-fpm и изменим владельца директории /var/www/html и директории PHP на www-data.

Определим том, чтобы смонтировать указанные ниже директории на хост:

Указываем порты для nginx

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

Вот весь скрипт Dockerfile целиком:

Теперь внутри директории с Dockerfile создайте новый файл конфигурации виртуального хоста под названием «default», файл конфигурации supervisord «supervisord.conf» и скрипт конфигурации сервисов «start.sh».

Вставьте в файл конфигурации виртуального хоста следующий код:

Откройте файл конфигурации Supervisord:

Вставьте следующий код конфигурации:

Откройте файл start.sh.

Вставьте следующие параметры конфигурации:

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

При помощи команды chmod сделайте файл start.sh исполняемым:

Создание нового образа и контейнера

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

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

Successfully built e7e5dc3d6cd1, говорит о том что образ создан. После успешного выполнения команды можно проверить наличие нового образа при помощи команды images:


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

Запустим новый контейнер командой run:

И командой ps проверим, запустился ли новый контейнер под названием my_container:


Разберем команду run более подробно:

Тестирование работы Nginx и PHP-FPM в контейнере

Командой echo создайте в директории /webroot новый файл index.html:

Тестирование при помощи доступа к IP-адресу хоста командой curl (замените 192.168.1.5 на свой IP-адрес):
curl 192.168.1.5
curl -I 192.168.1.5


Теперь проверим, что PHP-FPM 7.2 работает – создадим в директории /webroot новый файл c phpinfo.

Откройте веб-браузер и введите IP-адрес хоста:

Если все работает правильно, вы увидите следующий результат:


Заключение

Мы успешно создали новый образ и теперь можем создавать на его основе новые контейнеры. Более подробную информацию о создании образов и Dockerfile можно получить в документации Docker.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

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

Docker-образы

Docker-образ создаётся во время сборки, а Docker-контейнер — во время запуска приложения.

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

Sportmaster Lab , Санкт-Петербург , От 170 000 до 250 000 ₽

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

Инструкция Docker-файла — слово в верхнем регистре, которое стоит перед аргументом какой-либо команды. Каждая строка в Docker-файле может содержать инструкцию, все они обрабатываются сверху вниз. Инструкции выглядят так:

Эта статья предполагает использование Unix Docker-образа. Вы, конечно, можете использовать и Windows Docker-образ, но он медленнее, менее удобный и, вообще, его не часто применяют. Так что, пользуйтесь Unix по возможности.

Несколько Docker-инструкций

Инструкции и примеры к ним

Docker-файл чисто теоретически может содержать только одну строчку:

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

Заметьте, что этот Docker-файл содержит тег для базового образа: 18.04, который указывает Docker’у, какую именно версию образа нужно использовать. Если тег не указан, по умолчанию берётся последняя версия образа. Но лучше всё же указывать тег базового образа. Когда Docker-файл, приведённый выше, используется для создания локального Docker-образа впервые, он загружает слои, указанные в образе Ubuntu.

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

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

Подробнее про Docker-файл

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

Но что же это всё обозначает?

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

LABEL

Следующая инструкция — LABEL . LABEL добавляет метаданные к образу, предоставляет контактную информацию. Она не замедляет процесс запуска и не занимает много места, наоборот, обеспечивает образ полезной информацией, так что обязательно используйте её. Больше про LABEL читайте здесь.

ENV создаёт переменную окружения, которая становится доступной во время запуска контейнера. В примере выше вы могли видеть использование переменной ADMIN при создании контейнера.

ENV удобна для обозначения констант. Если константа используется в нескольких местах файла Dockerfile, и вам понадобится изменить её значение позднее, это можно будет сделать в одном месте.

Docker-файл зачастую предоставляет несколько путей решения одной задачи. Будет хорошо, если в вашем решении будет учитываться баланс Docker-соглашений, прозрачность и скорость. К примеру, RUN , CMD и ENTRYPOINT служат различным целям и могут использоваться для выполнения команд.

RUN создаёт слой во время запуска. Docker фиксирует состояние образа после каждой инструкции RUN .

apk — это сокращение от Alpine Linux package manager. Если вы используете базовый образ не Alpine Linux, то установка пакетов производится командой RUN apt-get .

RUN и её родственные инструкции: CMD , ENTRYPOINT — могут быть как форме оболочки, так и в форме shell-скрипта. Во втором случае используют JSON-синтаксис: RUN ["my_executable", "my_first_param1", "my_second_param2"] . А в примере выше использовалась форма оболочки: RUN apk update && apk upgrade && apk add bash .

Позднее в вашем Docker-файле вы будете создавать новую директорию, используя ["mkdir", "/a_directory"] . Не забывайте, что в JSON нужно использовать двойные кавычки!

Инструкция COPY . ./app говорит Docker’у, что нужно скопировать файлы и папки из вашей локальной сборки в рабочую директорию образа. COPY создаст все нужные папки, если они отсутствуют.

ADD делает то же самое, что и COPY , но с двумя отличиями. ADD может загружать файлы по URL, а также извлекать локальные TAR-файлы.

В примере выше ADD копировала файлы по URL внутрь директории контейнера. Но официальныя документация не рекомендует использовать ADD так, потому что потом вы попросту не сможете удалить файлы. А дополнительные файлы увеличивают размер образа.

CMD — инструкция для запуска чего-либо во время запуска самого контейнера. По ходу сборки она не фиксирует никакого результата. В примере выше во время сборки запускался скрипт my_script.py .

Ещё пара моментов о CMD :

  • Только одна CMD -инструкция на весь Docker-файл. Иначе все кроме последней будут проигнорированы;
  • CMD может включать исполняемый файл;
  • Если же CMD не содержит никакого файла, обязательно должна быть инструкция ENTRYPOINT . В этом случает обе инструкции должны быть в формате JSON;
  • Аргументы командной строки для запуска Docker переопределяют аргументы, предоставленные CMD в Docker-файле.

Готовы к большему?

В следующем примере представлены ещё несколько Docker-инструкций:

Для Alpine Docker-образа вы используете apk. apk для типичной Linux-сборки — apt-get . Например, пакеты для базового Ubuntu-образа могут быть установлены и обновлены так: RUN apt-get update && apt-get install my_package .

В дополнение к apk и apt-get , Python-пакеты могут быть установлены через pip, wheel и conda. Методы варьируются в зависимости от языка.

Нижележащие слои должны предоставить свое средство установки и управления пакетами. Если возникнет проблема с установкой пакетов, убедитесь, что у вас установлен менеджер пакетов.

Можно использовать RUN вместе с pip и списком нужных пакетов. Для этого объедините команды установки пакетов в одну инструкцию и разделите их символом продолжения строки ( \ ). Этот метод позволяет улучшить читаемость и уменьшить количество слоев (из-за отсутствия возможности использовать несколько RUN инструкций).

Также вы можете запустить установщик, указав ему файл, содержащий все зависимости для вашего образа. Обычно он называется requirements.txt.

WORKDIR

Меняет текущую рабочую директорию в контейнере для инструкций: COPY , ADD , RUN и ENTRYPOINT .

  • Предпочтительно задать абсолютный путь с помощью WORKDIR, а не перемещаться по файловой системе с помощью команд cd в Docker-файле;
  • WORKDIR автоматически создаёт директорию, если её ещё нет;
  • Можно использовать несколько WORKDIR -инструкций. Если используются относительные пути — каждая инструкция поменяет рабочую директорию.

Определяет переменную для передачи из командной строки в образ. Для ARG можно указать значение по умолчанию: ARG my_var=my_default_value .

В отличие от ENV -переменных, ARG -переменные не доступны для запущенных контейнеров. Однако вы можете использовать их для установки дефолтных значений для ENV -переменных, когда вы создаёте образ. И затем ENV-переменные сохраняются. Больше про это вы найдёте здесь.

ENTRYPOINT

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

Вместо этого аргументы командной строки, передаваемые docker run myimagename , добавляются к аргументам инструкции ENTRYPOINT . Например, docker run my_image bash добавляет аргумент bash в конец, ко всем другим аргументам ENTRYPOINT .

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

  • Если вам нужно запускать одну и туже команду несколько раз, выбирайте ENTRYPOINT ;
  • Используйте ENTRYPOINT , когда ваш контейнер выступает в роли исполняющейся программы;
  • При наличии дополнительных дефолтных аргументов, которые могут быть изменены через командную строку, лучше подойдёт CMD .

В примере выше, ENTRYPOINT ["python", "my_script.py", "my_var"] запускает в контейнере Python-скрипт my_script.py с аргументом my_var . Затем переменная my_var может быть использована в my_script argparse. Заметьте, у my_var есть дефолтное значение, ранее установленное в Docker-файле при помощи ARG . Так что, если аргумент не будет задан через командную строку, возьмётся его значение по умолчанию.

Как правило, Docker рекомендует вам использовать исполняемую форму с JSON-синтаксисом ENTRYPOINT ["executable", "param1", "param2"] .

EXPOSE

Инструкция EXPOSE показывает, какой порт пробрасывать из контейнера.

Используйте команду docker run с флагом -p для пробрасывания и сопоставления нескольких портов во время запуска. Флаг в верхнем регистре -P будет пробрасывать все открытые порты.

VOLUME

VOLUME определяет, где контейнер будет хранить постоянные данные и получать к ним доступ.

Заключение

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

Docker позволяет не только загружать и использовать готовые контейнеры, но создавать свои. В данной инструкции мы пошагово разберем установку Docker на Linux, создание собственного образа и загрузку его на Docker Hub.

Установка Docker

Рассмотрим примеры установки на базе операционных систем Red Hat/CentOS и Debian/Ubuntu.

Red Hat/CentOS

Устанавливаем репозиторий — для этого загружаем файл с настройками репозитория:

* если система вернет ошибку, устанавливаем wget командой yum install wget.

. и переносим его в каталог yum.repos.d:

mv docker-ce.repo /etc/yum.repos.d/

yum install docker-ce docker-ce-cli containerd.io

Если система вернет ошибку Необходимо: container-selinux >= . , переходим на страницу пакетов CentOS, находим нужную версию container-selinux и копируем на него ссылку:

Копирование ссылки на нужную версию container-selinux

. с помощью данной ссылки выполняем установку:

После повторяем команду на установку докера:

yum install docker-ce docker-ce-cli containerd.io

Debian/Ubuntu

В deb-системе ставится командой:

apt-get install docker docker.io

После установки

Разрешаем запуск сервиса docker:

systemctl enable docker

. и запускаем его:

systemctl start docker

docker run hello-world

. мы должны увидеть:

.
Hello from Docker!
This message shows that your installation appears to be working correctly.
.

Сборка нового образа

Сборка начинается с создания файла Dockerfile — он содержит инструкции того, что должно быть в контейнере. В качестве примера, соберем свой веб-сервер nginx.

И так, чтобы создать свой образ с нуля, создаем каталог для размещения Dockerfile:

mkdir -p /opt/docker/mynginx

* где /opt/docker/mynginx — полный путь до каталога, где будем создавать образ.

. переходим в данный каталог:

. и создаем Dockerfile:

RUN yum install -y epel-release && yum install -y nginx
RUN yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
RUN sed -i "0,/nginx/s/nginx/docker-nginx/i" /usr/share/nginx/html/index.html

* в данном файле мы:

  1. используем базовый образ centos 7;
  2. в качестве автора образа указываем Dmitriy Mosk;
  3. задаем временную зону внутри контейнера Europe/Moscow.
  4. устанавливаем epel-release и nginx;
  5. чистим систему от метаданных и кэша пакетов после установки;
  6. указываем nginx запускаться на переднем плане (daemon off);
  7. в индексном файле меняем первое вхождение nginx на docker-nginx;
  8. запускаем nginx.

* подробное описание инструкций Dockerfile смотрите ниже.

docker build -t dmosk/nginx:v1 .

* где dmosk — имя автора; nginx — название для сборки; v1 — тег с указанием версии. Точка на конце указывает, что поиск Dockerfile выполняем в текущей директории.

. начнется процесс сборки образа — после его завершения мы должны увидеть что-то на подобие:

Successfully built eae801eaeff2
Successfully tagged dmosk/nginx:v1

Посмотреть список образов можно командой:

Создаем и запускаем контейнер из образа:

docker run -d -p 8080:80 dmosk/nginx:v1

* в данном примере мы запустим контейнер из образа dmosk/nginx:v1 и укажем, что необходимо опубликовать внешний порт 8080, который будет перенаправлять трафик на порт 80 внутри контейнера.

Посмотреть созданные контейнеры можно командой:

Запустить или остановить контейнеры можно командами:

docker stop 5fe78aca2e1d

docker start 5fe78aca2e1d

* где 5fe78aca2e1d — идентификатор контейнера.

Редактирование образа

В примере выше мы рассмотрели создание нового образа с нуля. Также, мы можем взять любой другой образ, отредактировать его и сохранить под своим названием.

Скачаем образ операционной системы CentOS:

docker pull centos:latest

Войдем в скачанный образ для его изменения:

docker run -t -i centos:latest /bin/bash

Внесем небольшие изменения, например, создадим учетную запись:

* в данном примере мы создали пользователя dmosk и задали ему пароль.

docker commit -m "Add user dmosk" -a "Dmitry Mosk" 8f07ef93918f centos:my

* где -m — параметр для указания комментария; -a — указывает автора; 8f07ef93918f — идентификатор контейнера, который был нами изменен (его можно было увидеть в приглашении командной строки); centos:my — название нашего нового образа.

Новый образ создан.

Загрузка образа на Docker Hub

Заходим на Docker Hub страницу регистрации. Создаем пользователя:

Переходим на страницу Repositories и создаем свой репозиторий, например, dmosk. Теперь можно загрузить наши образы в репозиторий.

docker login --username dmosk

Задаем тег для одного из образов и загружаем его в репозиторий:

docker tag centos:my dmosk/dmosk:centos

docker push dmosk/dmosk:centos

Загрузим второй образ:

docker tag dmosk/nginx:v1 dmosk/dmosk:nginx

docker push dmosk/dmosk:nginx

В Docker Hub должны появиться наш образы:


docker login --username dmosk

docker pull dmosk/dmosk:nginx

docker run -d -p 8080:80 dmosk/dmosk:nginx

Описание инструкций Dockerfile

Резервное копирование и восстановление контейнера

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

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

И так, для создания резервной копии контейнера, смотрим их список:

. и для нужного выполняем команду:

docker save -o /backup/docker/container.tar <container image>

* в данном примере мы создаем архив контейнера <container image> в файл /backup/docker/container.tar.

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

* в итоге, мы получим файл container.tar.gz.

Восстановление

Сначала распаковываем архив:

После восстанавливаем контейнер:

docker load -i container.tar

Смотрим, что нужный нам контейнер появился:

Дополнительные команды

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

1. Удалить один образ:

docker rmi <название образа или его ID>

docker rmi dmosk/nginx:v1

2. Удалить все образы:

docker rmi $(docker images -q)

Мы можем получить ошибки на подобие:

Error response from daemon: conflict: unable to delete 857594f280c1 (must be forced) - image is being used by stopped container .

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

docker rm $(docker ps --filter status=exited -q)

Если нужно, можно остановить все действующие контейнеры командой:

docker stop $(docker ps -a -q)

Также мы можем принудительно удалить все образы, даже если они используются для контейнеров в данный момент:

docker rmi -f <название образа или его ID>

* добавлена опция -f.

3. Для выявления проблем при запуске или в работе контейнера очень полезна опция для просмотра логов:

Favorite

Добавить в избранное

Главное меню » Linux » Как скопировать файлы между хостом и Docker-контейнером

Установить Docker 1.11 на Ubuntu 16.04 LTS x64

Если вы хотите скопировать файлы из вашей хост-системы в контейнер, вы должны использовать команду docker cp, например:

Если вы хотите скопировать файлы из контейнера в хост-систему, используйте эту команду:

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

Примеры команды Docker cp

В нашей статье мы установили Docker на Ubuntu. Но шаги одинаковы для всех дистрибутивов, работающих под управлением Docker.

Мы надеемся, что вы знаете, как запустить Docker-контейнер, потому что вам нужен работающий контейнер.

Сначала перечислите ваши запущенные контейнеры, используя команду docker ps :

Если вы хотите убедиться, что файлы были успешно скопированы, вы можете ввести свой контейнер следующим образом, а затем использовать обычные команды Linux:

Копировать файлы из хост-системы в Docker-контейнер

Копирование с помощью docker cp аналогично команде копирования в Linux .

Мы собираемся скопировать файл с именем a.py в каталог home/dir1 в контейнере.

Если файл успешно скопирован, вы не увидите никакого вывода на экран. Если путь назначения не существует, вы увидите ошибку:

Если целевой файл уже существует, он будет перезаписан без предупреждения.

Вы также можете использовать идентификатор контейнера вместо имени контейнера:

Копировать файлы из Docker-контейнера в хост-систему

Команда docker cp выполняется только в хост-системе. Вы не можете запустить его в контейнере.

Даже если вы хотите скопировать файлы из Docker-контейнера в хост-систему, вам необходимо находиться в хост-системе и использовать команду следующим образом:

Копировать каталоги между контейнером и хост-системой

Если вы хотите скопировать каталог в Linux с помощью команды cp, вам придется использовать рекурсивную опцию -r.

Но в команде docker cp такие опции не нужны. Эта же команда работает для копирования файлов и папок.

Копировать файлы и каталоги с оригинальными атрибутами

Вы можете использовать режим архива при копировании с опцией -a. При этом вы можете скопировать все права доступа к файлу, UID и GID исходного файла.

Вот и все. Вы видите, как легко копировать файлы между хостом и контейнером с помощью команды docker cp.

Если у вас есть какие-либо вопросы или предложения, дайте нам знать в разделе комментариев.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Читайте также: