Как сгладить изображение докеров?
Я сделал контейнер Docker, который довольно большой. Когда я создаю контейнер для создания изображения, изображение имеет размер около 7.8 ГБ. Но когда я export
контейнер (не save
изображение!) В tarball и повторно импортирует его, изображение составляет всего 3 ГБ. Конечно, история потеряна, но это ОК для меня, так как изображение "сделано" на мой взгляд и готово к развертыванию.
Как сгладить изображение/контейнер, не экспортируя его на диск и импортируя его снова? И: Это разумная идея сделать это, или я пропустил какой-то важный момент?
Ответы
Ответ 1
До Docker 1.13 вы можете использовать флаг --squash
.
Перед версией 1.13:
Насколько я знаю, вы не можете использовать Docker api. docker export
и docker import
предназначены для этого сценария, как вы уже сами уже упоминаете.
Если вы не хотите сохранять на диск, вы, вероятно, могли бы вывести выходной поток экспорта во входной поток импорта. Я не тестировал это, но попробую
docker export red_panda | docker import - exampleimagelocal:new
Ответ 2
Теперь, когда Docker выпустил многоэтапные сборки в 17.05, вы можете переформатировать свою сборку, чтобы выглядеть так:
FROM buildimage as build
# your existing build steps here
FROM scratch
COPY --from=build / /
CMD ["/your/start/script"]
В результате ваши слои среды сборки будут кэшированы на сервере сборки, но в результирующем изображении, которое вы помечаете и нажимаете, будет существовать только сглаженная копия.
Примечание. Обычно вы переформулируете это, чтобы иметь сложную среду сборки и копировать только несколько каталогов. Вот пример с Go, чтобы сделать одно бинарное изображение из исходного кода и одной командой сборки без установки. Идите на хост и компилируйте вне докеров:
$ cat Dockerfile
ARG GOLANG_VER=1.8
FROM golang:${GOLANG_VER} as builder
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download
RUN go-wrapper install
FROM scratch
COPY --from=builder /go/bin/app /app
CMD ["/app"]
Файл go - это простой мир приветствия:
$ cat hello.go
package main
import "fmt"
func main() {
fmt.Printf("Hello, world.\n")
}
В сборке создаются среды, среда сборки и царапины, а затем теги:
$ docker build -t test-multi-hello .
Sending build context to Docker daemon 4.096kB
Step 1/9 : ARG GOLANG_VER=1.8
--->
Step 2/9 : FROM golang:${GOLANG_VER} as builder
---> a0c61f0b0796
Step 3/9 : WORKDIR /go/src/app
---> Using cache
---> af5177aae437
Step 4/9 : COPY . .
---> Using cache
---> 976490d44468
Step 5/9 : RUN go-wrapper download
---> Using cache
---> e31ac3ce83c3
Step 6/9 : RUN go-wrapper install
---> Using cache
---> 2630f482fe78
Step 7/9 : FROM scratch
--->
Step 8/9 : COPY --from=builder /go/bin/app /app
---> Using cache
---> 5645db256412
Step 9/9 : CMD /app
---> Using cache
---> 8d428d6f7113
Successfully built 8d428d6f7113
Successfully tagged test-multi-hello:latest
При просмотре изображений в отправляемом изображении только один бинарный файл, в то время как среда сборки составляет более 700 МБ:
$ docker images | grep 2630f482fe78
<none> <none> 2630f482fe78 6 days ago 700MB
$ docker images | grep 8d428d6f7113
test-multi-hello latest 8d428d6f7113 6 days ago 1.56MB
И да, он работает:
$ docker run --rm test-multi-hello
Hello, world.
Ответ 3
Создайте изображение с флагом --squash
:
https://docs.docker.com/engine/reference/commandline/build/#squash-an-images-layers-squash-experimental-only
Также рассмотрите возможность удаления ненужных файлов, таких как кэш apt:
RUN apt-get clean && rm -rf/var/lib/apt/lists/*/tmp/*/var/tmp/*