有没有一种方法可以将Docker映像合并到一个容器中?


79

我现在有几个Dockerfile。

一种是Cassandra 3.5,它是 FROM cassandra:3.5

我也有一个针对Kafka的Dockerfile,但是要复杂得多。它是,FROM java:openjdk-8-fre并且它运行长命令来安装Kafka和Zookeeper。

最后,我有一个用Scala编写的使用SBT的应用程序。

对于Dockerfile,它是FROM broadinstitute/scala-baseimage,这使我得到了Java 8,Scala 2.11.7和STB 0.13.9。

也许,我不了解Docker的工作原理,但我的Scala程序将Cassandra和Kafka作为依赖项,出于开发目的,我希望其他人能够简单地使用克隆我的仓库,Dockerfile然后再使用Cassandra,Kafka来构建它。 ,Scala,Java和SBT都加入进来,因此它们只能编译源代码。我对此有很多问题。

如何合并这些Dockerfile?我如何简单地将这些东西放入一个环境中?


6
您不合并Docker
generalhenry 2016年

@generalhenry,如果我愿意,我不能只是复制并粘贴获得Cassandra 3.5所需的docker东西,然后将其放入我的Java,Scala和SBT的主Dockerfile中吗?
大卫

尽管您可以使所有内容都在单个容器中运行,但这并不是很理想。容器使您可以清晰地分离网络,扩展,日志记录,监视等。。。
generalhenry

1
@generalhenry当然,这通常是您想要做的。但是,如果您需要锈蚀以从PyPi编译二进制python包怎么办?在这种情况下,您可能需要结合使用rust和python docker镜像。组成它们是行不通的。
Tobias Bergkvist

Answers:


89

您可以使用Docker 1.17中引入的多阶段构建功能

看看这个:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

然后正常构建映像:

docker build -t alexellis2/href-counter:latest

来自:https : //docs.docker.com/develop/develop-images/multistage-build/

最终结果是与以前相同的微小生产映像,并大大降低了复杂性。您不需要创建任何中间映像,也不需要将任何工件提取到本地系统。

它是如何工作的?第二条FROM指令以alpine:latest图像为基础开始新的构建阶段。COPY --from = 0行仅将之前阶段的构建工件复制到此新阶段。Go SDK和任何中间工件都被保留了下来,没有保存在最终图像中。


5
假设我想合并两个基本映像,这些映像正在运行并且不是我自己维护的。例如,如果我想运行具有GPU加速锈蚀的应用程序,我希望我的形象是合并nvidia-dockerrustlang/rust:nightly。这些图像又位于其他图像之上。为了使用多层构建来执行此操作,我必须知道并指定要复制到另一个映像中的一个映像中的所有文件-似乎是不可能的,尤其是当上游映像更改时,该集可能会更改。我读对了吗?
masonk

3
@masonk我已经成功完成了:FROM a/a:latest FROM b/b:latest COPY --from=0 / / 可能很糟糕的做法,但是确实有效。这主要是出于我自己的好奇心,而不是我在生产中使用的东西。
McP

4
该死的东西对我不起作用。就像第一个“ FROM”被完全忽略了一样。
DimiDak

同样在这里:我想做FROM image1; CMD image1command; FROM image2; CMD image2command;这根本没有用。永远只是第二个命令
CGFoX

那打败了拥有容器的目的,不是吗?
Luiz Felipe

22

您无法合并dockerfile,因为可能会发生冲突。您要做的是创建一个新的dockerfile或构建一个自定义映像。

TL; DR; 如果您当前的开发容器包含您需要和可以使用的所有工具,则将其另存为映像并保存到仓库中,并创建一个dockerfile从该映像中提取该仓库。

详细信息:与使用公共映像创建dockerfile相比,构建自定义映像要容易得多,因为您可以将任何hack和mods存储到映像中。为此,请使用基本的Linux映像(或broadinstitute / scala-baseimage)启动一个空白容器,安装所需的工具并对其进行配置,直到一切正常为止,然后将其(容器)另存为映像。在该图像上创建一个新容器,并测试是否可以通过docker-compose在其之上构建代码(或者您想执行/构建它)。如果可行,则您拥有一个可以正常工作的基础映像,可以将其上传到存储库,以便其他人可以提取它。

要使用公共映像构建dockerfile,您需要将所有hack,mod和设置都放置在dockerfile本身上。也就是说,您将需要将使用的每个命令行放入文本文件中,并减少任何hacks,mod和安装程序。最后,您的dockerfile会自动创建一个映像,您不需要将该映像存储到存储库中,您需要做的就是将其他dockerfile交给他人,他们可以在自己的docker上旋转该映像。

请注意,一旦有了一个可用的dockerfile,便可以轻松对其进行调整,因为每次使用dockerfile时都会创建一个新映像。对于自定义映像,由于冲突,您可能会遇到需要重建映像的问题。例如,所有工具都可以与openjdk一起使用,直到您安装了不起作用的工具为止。该修补程序可能涉及卸载openjdk并使用oracle,但您为已安装的所有工具所做的所有配置都已损坏。


9

以下答案适用于Docker 1.7及更高版本:

我更喜欢使用--from=NAMEfrom image as NAME 为什么?您可以使用--from=0及以上版本,但是当您在dockerfile中有许多Docker阶段时,这可能很难管理。

示例示例:

FROM golang:1.7.3 as backend
WORKDIR /backend
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN  #install some stuff, compile assets....

FROM golang:1.7.3 as assets
WORKDIR /assets
RUN ./getassets.sh

FROM nodejs:latest as frontend 
RUN npm install
WORKDIR /assets
COPY --from=assets /asets .
CMD ["./app"] 

FROM alpine:latest as mergedassets
WORKDIR /root/
COPY --from=merge ./
COPY --from=backend ./backend .
CMD ["./app"]

注意:正确管理dockerfile将有助于更快地构建docker映像。内部docker使用docker层缓存来帮助完成此过程,以防必须重建映像。


6

是的,您可以将很多软件整合到一个Docker映像中(GitLab可以做到这一点,其中一个映像包含Postgres和其他所有内容),但是generalhenry是正确的-这不是使用Docker的典型方法。

如您所说,Cassandra和Kafka是Scala应用程序的依赖项,它们不属于应用程序,因此它们并不全都属于同一映像。

必须使用Docker Compose来协调许多容器,这增加了一个额外的管理层,但是它为您提供了更大的灵活性:

  • 您的容器可以有不同的寿命,因此当您要部署新版本的应用程序时,只需要运行一个新的应用程序容器,就可以使依赖项保持运行状态;
  • 您可以在任何环境中使用相同的应用程序映像,并为依赖项使用不同的配置-例如,在dev中,您可以运行基本的Kafka容器,并且在生产中将其群集在多个节点上,您的应用程序容器是相同的;
  • 您的依赖关系也可以被其他应用程序使用-因此,多个使用者可以在不同的容器中运行,并且所有工作都可以在同一个Kafka和Cassandra容器中进行;
  • 加上已经提到的所有可伸缩性,日志记录等。


2

Docker不会合并图像,但是没有什么可以阻止您组合dockerfile(如果可用),并将其滚动成一个需要构建的胖图像。有时候,这是有道理的,因为对于在容器中运行多个进程而言,大多数Docker教条会指出这一点不那么理想,尤其是在微服务架构中(但是要打破规则吗?)


1

我需要Gitlab CI的docker:latest和python:latest图像。这是我想出的:

FROM ubuntu:latest
RUN apt update
RUN apt install -y sudo
RUN sudo apt install -y docker.io
RUN sudo apt install -y python3-pip
RUN sudo apt install -y python3
RUN docker --version
RUN pip3 --version
RUN python3 --version

构建并推送到Docker Hub存储库后:

docker build -t docker-hub-repo/image-name:latest path/to/Dockerfile
docker push docker-hub-repo/image-name:latest

docker login推送前别忘了

希望能帮助到你

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.