Какие способы передачи исходного кода в Docker контейнер существуют
Что проверяют
Понимаете ли вы разницу между кодом, запечённым в образ при сборке, и кодом, примонтированным в работающий контейнер, и когда что уместно. Для Go следом почти всегда спрашивают про многоэтапную сборку и кэш зависимостей.
Как отвечать
При сборке образа:
COPYиз контекста сборки: пути считаются от контекста, а не от корня диска, лишнее отсекает.dockerignore;- многоэтапная сборка: первая стадия на образе
golangкомпилирует, финальная берёт только бинарник вgcr.io/distroless/staticилиscratch. СCGO_ENABLED=0бинарник статический, и образ весит мегабайты вместо сотен мегабайт; - порядок слоёв: сначала
COPY go.mod go.sum ./иRUN go mod download, потомCOPY . .. Правка кода не трогает слой с зависимостями; - монтирования BuildKit:
RUN --mount=type=cache,target=/go/pkg/modи такой же кэш для/root/.cache/go-build,--mount=type=bind, чтобы не копировать исходники в слой,--mount=type=sshилиtype=secretдля приватных модулей; - контекст из Git:
docker buildпринимает URL репозитория, аADDв BuildKit умеет клонировать репозиторий безgitвнутри образа.
В работающий контейнер:
- bind mount:
docker run -v "$PWD":/appилиvolumesв Compose, вместе сairдля пересборки при изменении файлов. Только для локальной разработки; docker compose watch: секцияdevelop.watch, для компилируемого Go обычно действиеrebuild;docker cp: разовая подкладка файла при отладке.
Где спотыкаются
Пишут COPY . . до скачивания модулей. Любая правка кода сбрасывает кэш, и go mod download выполняется при каждой сборке заново.
Клонируют приватный репозиторий с токеном в ARG или ENV. Токен остаётся в метаданных образа и виден через docker history, для секретов есть --mount=type=secret.
Тащат в прод образ golang с исходниками и компилятором. Он весит сотни мегабайт, расширяет поверхность атаки, а без .dockerignore туда же попадают .git и локальные .env.