Docker 이미지를 하나의 컨테이너로 결합하는 방법이 있습니까?


86

지금 Dockerfile이 몇 개 있습니다.

하나는 Cassandra 3.5 용이며 FROM cassandra:3.5

또한 Kafka 용 Dockerfile도 있지만 t는 훨씬 더 복잡합니다. 그것은 FROM java:openjdk-8-freKafka와 Zookeeper를 설치하기 위해 긴 명령을 실행합니다.

마지막으로 SBT를 사용하는 Scala로 작성된 애플리케이션이 있습니다.

해당 Dockerfile의 경우 FROM broadinstitute/scala-baseimageJava 8, Scala 2.11.7 및 STB 0.13.9가 필요합니다.

아마도 Docker가 어떻게 작동하는지 이해하지 못하지만 내 Scala 프로그램에는 Cassandra와 Kafka가 종속성으로 있으며 개발 목적으로 다른 사람들이 내 저장소를 단순히 복제 Dockerfile한 다음 Cassandra, Kafka로 빌드 할 수 있기를 바랍니다. , Scala, Java 및 SBT는 모두 소스를 컴파일 할 수 있도록 구워졌습니다. 그래도 이것에 많은 문제가 있습니다.

이러한 Dockerfile을 어떻게 결합합니까? 구워진 것들로 어떻게 환경을 만들 수 있습니까?


6
당신은 고정 표시기의 이미지를 결합하지 않는, 당신은 그 구성 : docs.docker.com/compose
generalhenry

@generalhenry 원하는 경우 Cassandra 3.5를 가져 오는 데 필요한 도커 항목을 복사하여 붙여넣고 Java, Scala 및 SBT를 제공하는 기본 Dockerfile에 넣을 수는 없습니까?
David

모든 것을 단일 컨테이너에서 실행할 수 있지만 바람직하지 않습니다. 컨테이너를 사용하면 네트워킹, 확장, 로깅, 모니터링 등을 명확하게 분리 할 수 ​​있습니다. . .
generalhenry

2
@generalhenry 물론, 그게 종종 당신이 원하는 일입니다. 하지만 PyPi에서 바이너리 파이썬 패키지를 컴파일하기 위해 rust가 필요하다면 어떨까요? 이 경우 rust와 python docker 이미지를 결합 할 수 있습니다. 구성은 작동하지 않습니다.
Tobias Bergkvist

답변:


92

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 및 모든 중간 아티팩트는 남아 있으며 최종 이미지에 저장되지 않습니다.


7
많은 일이 진행되고 내가 관리하지 않는 두 개의 기본 이미지를 결합하고 싶다고 가정 해 보겠습니다. 예를 들어 GPU 가속 기능이있는 Rust 앱을 실행하려면 내 이미지가 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을 결합 할 수 없습니다. 원하는 것은 새 도커 파일을 만들거나 사용자 지정 이미지를 만드는 것입니다.

TL; DR; 현재 개발 컨테이너에 필요한 모든 도구가 포함되어 있고 작동하는 경우 이미지로 저장하고 그 위에 저장소에 저장하고 해당 저장소에서 해당 이미지를 가져올 dockerfile을 만듭니다.

세부 정보 : 사용자 지정 이미지를 만드는 것은 공개 이미지를 사용하여 도커 파일을 만드는 것보다 훨씬 쉽습니다. 모든 해킹과 모드를 이미지에 저장할 수 있기 때문입니다. 이렇게하려면 기본 Linux 이미지 (또는 broadinstitute / scala-baseimage)로 빈 컨테이너를 시작하고 필요한 도구를 설치하고 모든 것이 올바르게 작동 할 때까지 구성한 다음 이미지로 저장합니다 (컨테이너). 이 이미지에서 새 컨테이너를 만들고 docker-compose를 통해 코드를 빌드 할 수 있는지 테스트합니다 (또는 원하는대로 수행 / 빌드). 작동하는 경우 다른 사람이 가져올 수 있도록 저장소에 업로드 할 수있는 작업 기본 이미지가 있습니다.

공개 이미지로 dockerfile을 빌드하려면 모든 해킹, 모드 및 설정을 dockerfile 자체에 배치해야합니다. 즉, 사용한 모든 명령 줄을 텍스트 파일에 배치하고 모든 해킹, 모드 및 설정을 명령 줄로 줄여야합니다. 결국 dockerfile은 이미지를 자동으로 생성하고이 이미지를 저장소에 저장할 필요가 없으며 다른 사람에게 dockerfile을 제공하면 다른 사람이 자신의 docker에서 이미지를 회전 할 수 있습니다.

일단 작동하는 dockerfile이 있으면 dockerfile을 사용할 때마다 새 이미지가 생성되므로 쉽게 조정할 수 있습니다. 사용자 지정 이미지를 사용하면 충돌로 인해 이미지를 다시 빌드해야하는 문제가 발생할 수 있습니다. 예를 들어 모든 도구는 작동하지 않는 도구를 설치할 때까지 openjdk와 함께 작동합니다. 수정 사항에는 openjdk를 제거하고 oracle을 사용하는 것이 포함될 수 있지만 설치 한 모든 도구에 대해 수행 한 모든 구성이 손상되었습니다.


이 답변은 다단계 빌드가 도입 된 이후로 구식입니다.
slikts

9

다음 답변은 docker 1.7 이상에 적용됩니다.

사용 --from=NAME하고 싶은데 from 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 레이어 캐싱을 사용합니다.


7

예, 많은 소프트웨어를 단일 Docker 이미지로 롤링 할 있지만 ( GitLab 은 Postgres 및 기타 모든 것을 포함하는 하나의 이미지 로이 작업을 수행합니다) generalhenry 가 옳습니다. Docker를 사용하는 일반적인 방법은 아닙니다.

말했듯이 Cassandra와 Kafka는 Scala 앱의 종속성 이며 앱의 일부가 아니므로 모두 동일한 이미지에 속하지 않습니다.

Docker Compose를 사용하여 많은 컨테이너를 오케스트레이션하면 추가 관리 계층이 추가되지만 훨씬 더 많은 유연성이 제공됩니다.

  • 컨테이너의 수명이 다를 수 있으므로 배포 할 앱의 새 버전이있는 경우 새 앱 컨테이너를 실행하기 만하면되고 종속성은 실행 상태로 둘 수 있습니다.
  • 종속성에 대해 서로 다른 구성을 사용하여 모든 환경에서 동일한 앱 이미지를 사용할 수 있습니다. 예를 들어 dev에서는 기본 Kafka 컨테이너를 실행할 수 있으며 prod에서는 여러 노드에 클러스터링 할 수 있습니다. 앱 컨테이너는 동일합니다.
  • 종속성은 다른 앱에서도 사용할 수 있습니다. 따라서 여러 소비자가 서로 다른 컨테이너에서 실행될 수 있고 모두 동일한 Kafka 및 Cassandra 컨테이너에서 작동합니다.
  • 추가로 이미 언급 한 모든 확장 성, 로깅 등.

4

Docker 이미지를 하나의 컨테이너로 결합 할 수 없습니다. Moby 문제, Dockerfile을 통해 여러 이미지를 하나로 결합하는 방법 에 대한 자세한 논의를 참조하십시오 .

귀하의 경우 전체 Cassandra 및 Kafka 이미지를 포함하지 않는 것이 좋습니다. 애플리케이션에는 Cassandra Scala 드라이버와 Kafka Scala 드라이버 만 필요합니다. 컨테이너에는 드라이버 만 포함되어야합니다.


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푸시 하기 전에 잊지 마세요

도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.