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.