ЯдроКодаподготовка к экзаменам
Учебная платформа

Загружаем материалы

Подготавливаем материалы и навигацию по разделу.

Dockerfile и docker build: контекст, -f, -t и ошибка requires 1 argument

Автор: · Обновлено

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

Полный минимальный пример Dockerfile

В отдельной папке build-first создайте файл message.txt со строкой Docker build работает, а рядом — Dockerfile:

FROM alpine:3.22
WORKDIR /lesson
COPY message.txt ./message.txt
CMD ["cat", "/lesson/message.txt"]

Соберите и запустите:

docker build -t dk-message:1 .
docker run --rm dk-message:1
docker image inspect dk-message:1 --format '{{.Id}}'

Ожидаемый вывод run — содержимое message.txt. FROM выбирает основу, WORKDIR задаёт рабочую директорию, COPY добавляет файл в образ, CMD задаёт команду контейнера. Во время сборки CMD не выполняется. Для команды этапа сборки существует RUN. Справочник Dockerfile.

Что значит docker build -t

Флаг -t или --tag присваивает результату имя repository:tag. Здесь repository — dk-message, tag — 1. Это удобная ссылка на образ, а не имя будущего контейнера и не путь к Dockerfile. Несколько тегов могут указывать на один образ.

Точка в конце — один позиционный аргумент, текущая директория как build context. Строка docker build -t dk-message:1 неполна. В современном Docker она может завершиться сообщением docker: 'docker buildx build' requires 1 argument либо близким по форме сообщением. Упоминание Buildx не означает, что нужно переписать Dockerfile.

Исправление:

docker build -t dk-message:1 .
docker buildx build --load -t dk-message:1 .

Если контекст содержит пробелы, заключайте путь в кавычки: docker build -t dk-message:1 "./my project". Два незакавыченных слова превращаются в два позиционных аргумента; пропущенный путь — в ноль. Оба случая нарушают требование одного контекста. Синтаксис build.

Dockerfile в другой папке

Допустим, структура такая:

project/
  message.txt
  docker/
    Dockerfile

Из project выполните docker build -f docker/Dockerfile -t dk-message:2 .. Источник COPY message.txt ищется в корне контекста, а не рядом с Dockerfile. Если выбрать контекст ./docker, message.txt окажется за его пределами. Попытка COPY ../message.txt не открывает сборщику доступ к произвольным файлам компьютера: выберите подходящий корень контекста. Правила контекста.

docker build и docker image build

docker image build — форма команды в группе image, а docker build — привычная короткая форма. Они не задают разные форматы образа. Buildx — клиент расширенной системы сборки BuildKit; при работе с отдельными builders важно проверять выбор builder и экспорт результата. Для начинающего вопрос «в чём разница между docker build и docker image build» решается экспериментом с одним Dockerfile и тем же контекстом, а не поиском особого синтаксиса COPY.

CMD и ENTRYPOINT: команда и аргументы по умолчанию

В нашем первом образе задан только CMD. Поэтому docker run --rm dk-message:1 echo overridden заменяет команду cat целиком и печатает overridden. Когда образ должен вести себя как конкретная утилита, удобно задать exec-форму ENTRYPOINT, а CMD оставить её аргументами по умолчанию.

В той же папке создайте Dockerfile.entrypoint:

FROM alpine:3.22
ENTRYPOINT ["echo"]
CMD ["default-message"]
docker build -f Dockerfile.entrypoint -t dk-entry:1 .
docker run --rm dk-entry:1
docker run --rm dk-entry:1 custom-message
docker run --rm --entrypoint cat dk-entry:1 /etc/alpine-release

Первые два запуска печатают default-message и custom-message: аргумент после имени образа заменяет CMD, сохраняя ENTRYPOINT. Третий явно заменяет программу через --entrypoint. Shell-форма имеет другие правила обработки аргументов и сигналов; для предсказуемого запуска программы начинайте с JSON-массива и отдельно разбирайте необходимость shell. Сочетание CMD и ENTRYPOINT. Удалите после опыта только тег dk-entry:1.

COPY и ADD: обычное копирование и дополнительные операции

Для локальных исходников используйте COPY: он явно переносит файл или каталог из разрешённого контекста. ADD умеет больше, в том числе получать поддерживаемые удалённые источники и распаковывать локальные tar-архивы. Это меняет результат: COPY bundle.tar /app/ оставляет архив, а ADD bundle.tar /app/ распаковывает распознаваемый локальный tar в /app. Распаковка определяется содержимым архива; не считайте любой файл с расширением .tar архивом. Правила ADD.

У удалённых URL другие правила: не переносите автоматическую распаковку локального tar на любой загруженный архив. Если скачивание необходимо, зафиксируйте источник и проверку целостности поддерживаемым способом. ADD не даёт доступа к произвольным файлам вне build context и не заменяет безопасную передачу секретов. Выбор инструкции должен объяснять требуемую операцию, а не опираться на миф «ADD всегда лучше COPY».

Если файл не найден

При failed to compute cache key прочитайте строку с отсутствующим путём. Проверьте рабочую папку, имя файла с учётом регистра и исключения .dockerignore. Файл может существовать на диске и одновременно отсутствовать в переданном контексте. Если вместо инструкции Dockerfile выдаётся unknown instruction, проверьте, не сохранён ли в файл Markdown с тройными кавычками.

Упражнение

Переместите Dockerfile в docker/, оставив message.txt в корне. Соберите тег dk-message:2 с правильными -f и контекстом. Затем измените сообщение, соберите :3 и сравните вывод старого и нового образов. Старый образ должен показывать прежний текст: изменение исходника на компьютере само по себе не переписывает уже собранный образ. После упражнения удалите только свои учебные теги через docker image rm dk-message:1 dk-message:2 dk-message:3.

Источники