Чи є спосіб поєднати зображення Docker в 1 контейнер?


86

Зараз у мене є кілька файлів Docker.

Один призначений для Cassandra 3.5, і він є FROM cassandra:3.5

У мене також є файл Docker для Кафки, але він є набагато складнішим. Це FROM java:openjdk-8-freі виконує довгу команду, щоб встановити Kafka та Zookeeper.

Нарешті, у мене є програма, написана на Scala, яка використовує SBT.

Для цього файлу Docker це FROM broadinstitute/scala-baseimage, що я отримую мені Java 8, Scala 2.11.7 і STB 0.13.9, що мені потрібно.

Можливо, я не розумію, як працює Docker, але в моїй програмі Scala Кассандра та Кафка є залежностями, а для цілей розробки я хочу, щоб інші могли просто клонувати моє репо за допомогою, Dockerfileа потім могли будувати його разом із Кассандрою, Кафкою , Scala, Java і SBT - все це запекло, щоб вони могли просто скомпілювати джерело. У мене з цим багато проблем.

Як поєднати ці файли Docker? Як я можу просто створити оточення з тими речами, запеченими?


6
Ви не комбінуєте зображення докера
generalhenry

@generalhenry, якщо я хотів, чи не міг я просто скопіювати та вставити матеріали докера, необхідні для отримання Cassandra 3.5, і помістити це в мій основний файл Docker, який отримує мені Java, Scala та SBT?
Девід

Хоча ви могли б запустити все в одному контейнері, це рідко бажано. Контейнери дозволяють вам чітко відокремити ваші мережі, масштабування, реєстрацію, моніторинг тощо. . .
generalhenry

2
@generalhenry Звичайно, це саме те, що ти хочеш робити. Але що, якщо вам потрібна іржа для компіляції двійкового пакету python з PyPi? У цьому випадку вам може знадобитися поєднати зображення іржі та докера python. Складання їх не буде працювати.
Тобіас Бергквіст,

Відповіді:


91

Ви можете, завдяки функції багатоступеневих збірок, представленій у 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 розпочинає новий етап побудови з основою альпійського: найновішого зображення. Рядок COPY --from = 0 копіює лише вбудований артефакт з попереднього етапу на цей новий етап. Go SDK та будь-які проміжні артефакти залишаються позаду і не зберігаються на кінцевому зображенні.


7
Припустимо, я хочу поєднати два базових зображення, які багато в чому відбуваються і не підтримуються мною. Наприклад, якщо я хочу запустити додаток Rust, що має прискорення графічного процесора, я хочу, щоб моє зображення було об'єднанням nvidia-dockerі rustlang/rust:nightly. Ці зображення, в свою чергу, накладаються поверх інших зображень. Для того, щоб зробити це за допомогою багатошарових збірок, я повинен знати і вказати всі файли одного із зображень, які я хочу скопіювати на інше зображення - здається неможливим, особливо, оскільки цей набір може змінюватися, коли змінюється зображення вище за течією. Чи правильно я читаю це?
masonk

3
@masonk Я мав успіх: FROM a/a:latest FROM b/b:latest COPY --from=0 / / Можливо, це жахлива практика, але це працює. Це було здебільшого для власної цікавості, ніж те, що я використав би у виробництві.
McP

4
Проклята річ у мене не працює. Це як перший "ВІД" повністю ігнорується.
DimiDak

Те саме тут: я хочу зробити FROM image1; CMD image1command; FROM image2; CMD image2command;Це взагалі не працює. Завжди лише 2-а команда
CGFoX

що перемагає мету наявності контейнерів, чи не так?
Луїс Феліпе

22

Не можна поєднувати докер-файли, оскільки можуть виникнути конфлікти. Що ви хочете зробити, це створити новий докер-файл або створити власний образ.

TL; DR; Якщо ваш поточний контейнер розробки містить усі необхідні вам інструменти та працює, збережіть його як зображення та на ньому до репозиторію та створіть файл docker для вилучення з цього зображення з цього репо.

Подробиці: Створення власного образу набагато простіше, ніж створення докер-файлу за допомогою загальнодоступного образу, оскільки ви можете зберігати в зображенні всі хаки та моди. Для цього запустіть порожній контейнер з базовим образом Linux (або broadinstitute / scala-baseimage), встановіть будь-які потрібні вам інструменти та налаштуйте їх, поки все не спрацює правильно, а потім збережіть його (контейнер) як зображення. Створіть новий контейнер на цьому зображенні та перевірте, чи можете ви створити свій код поверх нього за допомогою docker-compose (або як ви хочете зробити / побудувати його). Якщо це працює, тоді у вас є робоче базове зображення, яке ви можете завантажити в репо, щоб інші могли його витягнути.

Щоб створити докер-файл із загальнодоступним образом, вам потрібно буде розмістити всі хаки, моди та налаштування на самому докер-файлі. Тобто вам потрібно буде розмістити кожен командний рядок, який ви використовували, у текстовий файл і зменшити будь-які хаки, моди та налаштування в командні рядки. Врешті-решт ваш файл docker автоматично створить зображення, і вам не потрібно зберігати це зображення в репо, а все, що вам потрібно зробити, це надати іншим файл докера, і вони можуть обертати зображення у своєму власному докері.

Зверніть увагу, що коли у вас є робочий файл docker, ви можете легко його налаштувати, оскільки він створюватиме новий образ кожного разу, коли ви використовуєте файл docker. З користувацьким зображенням ви можете зіткнутися з проблемами, коли вам потрібно відновити образ через конфлікти. Наприклад, усі ваші інструменти працюють з openjdk, доки ви не встановите той, який не працює. Виправлення може передбачати видалення openjdk та використання оракула, але вся конфігурація, яку ви зробили для всіх встановлених інструментів, зламалася.


9

Наступна відповідь стосується docker 1.7 і вище:

Я вважаю за краще використовувати --from=NAMEі from image as NAME чому? Ви можете використовувати --from=0і вище, але це може трохи важко управляти, коли у вас є багато стадій докера у файлі докер.

зразок прикладу:

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"]

Примітка: Правильне керування файлом docker допоможе швидше створити образ докера. Внутрішнє використання докера використовує кешування шарів докера, щоб допомогти в цьому процесі, якщо зображення потрібно перебудувати.


7

Так, ви можете згорнути цілий ряд програмного забезпечення в одне зображення Docker ( GitLab робить це, з одним зображенням, що включає Postgres та все інше), але generalhenry має рацію - це не типовий спосіб використання Docker.

Як ви кажете, Кассандра та Кафка є залежностями для вашої програми Scala, вони не є частиною програми, тому вони не належать до одного зображення.

Необхідність оркеструвати багато контейнерів за допомогою Docker Compose додає додатковий рівень адміністратора, але це дає набагато більшу гнучкість:

  • ваші контейнери можуть мати різну тривалість життя, тому, коли у вас є нова версія програми для розгортання, вам потрібно лише запустити новий контейнер програми, ви можете залишити залежності запущеними;
  • ви можете використовувати одне і те ж зображення додатка в будь-якому середовищі, використовуючи різні конфігурації для ваших залежностей - наприклад, у dev ви можете запустити базовий контейнер Kafka, а в prod його кластеризувати на багатьох вузлах, контейнер вашого додатка однаковий;
  • ваші залежності можуть використовуватись і іншими програмами - тому багато споживачів можуть працювати в різних контейнерах і всі працювати з однаковими контейнерами Kafka та Cassandra;
  • плюс вся згадана масштабованість, реєстрація тощо.

4

Не вдалося об’єднати зображення докера в 1 контейнер. Див. Детальні обговорення у випуску Moby, Як об’єднати кілька зображень в одне через Dockerfile .

Для вашого випадку краще не включати цілі зображення Кассандри та Кафки. Програмі знадобиться лише драйвер Cassandra Scala та драйвер Kafka Scala. Контейнер повинен містити лише драйвери.


2

Docker не робить злиття зображень, але ніщо не заважає вам поєднувати файли docker, якщо вони є, і згортати їх у жирне зображення, яке вам потрібно буде створити. Однак бувають випадки, коли це має сенс, що стосується запуску декількох процесів у контейнері, то більшість догм Docker вказуватимуть на це як на менш бажане, особливо в архітектурі мікросервісів (проте правила тут повинні бути порушені, чи не так?)


1

Мені потрібен докер: останнє та python: останні зображення для Gitlab CI. Ось що я придумав:

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перед натисканням

Сподіваюся, це допоможе

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.