Docker Compose vs. Dockerfile-어느 것이 더 낫습니까?


384

Docker 에 대해 읽고 배우고 있으며 사용할 Django 설정을 올바르게 선택하려고합니다. 지금까지 다음 중 하나가 있습니다.

도커 작성 또는 도커 파일

Dockerfiles에서 사용되는 것을 이해 Docker Compose하지만 FROM다른 이미지에 대해 여러 명령을 사용하여 하나의 큰 Dockerfile에 모든 것을 넣는 것이 좋은지 확실하지 않습니까?

다음과 같은 여러 가지 다른 이미지를 사용하고 싶습니다.

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Docker를 사용하여 이러한 유형의 환경을 설정하는 모범 사례에 대해 조언하십시오 .

도움이된다면 Mac에 있으므로 boot2docker 사용 하십시오 .

내가 가진 몇 가지 문제 :

  1. Docker Compose는 Python3과 호환되지 않습니다
  2. 내 프로젝트를 컨테이너화하고 싶기 때문에 하나의 큰 Dockerfile이 이상적이지 않으면 Docker Compose를 사용하여 분해해야한다고 생각합니다.
  3. Py2 및 Py3 프로젝트를 호환 가능하게 만들었으므로 장고 작성에 기대어 있습니다.

5
"단일 또는 여러 컨테이너로 앱을 실행해야합니까?" 그것은 의존적이며 우려의 규모 및 분리 문제 (서비스 당 하나의 컨테이너)를 고려해야합니다. 도움이 될 수 있습니다 : stackoverflow.com/questions/30534939/…quora.com/…
Fabien Snauwaert

도커의 공식 "시작"문서 .
jchook

답변:


238

대답은 없습니다.

Docker Compose (여기에서 compose라고 함)는 프로젝트에 build 명령을 추가하면 Dockerfile을 사용합니다 docker-compose.yml.

Docker 워크 플로는 만들려는 Dockerfile각 이미지에 적합한 것을 빌드 한 다음 compose를 사용하여 build명령을 사용하여 이미지를 어셈블해야합니다 .

당신은 사용하여 개별 Dockerfiles의 경로를 지정할 수 있습니다 build /path/to/dockerfiles/blah어디 /path/to/dockerfiles/blah어디 어쩌구의입니다 Dockerfile삶.


10
docker-compose프로덕션에서 사용 합니까 아니면 개발자 만 사용 하십니까? 당신의 도움을 주셔서 감사합니다.
Aaron Lelevier

18
@booyaa 좀 더 자세히 설명해 주시겠습니까?
마틴 토마

2
답변 해주셔서 감사합니다! Dockerfile은 이미지의 구성을 지정하고 docker-compose.yml은 이미지를 함께 어셈블합니다. 지적하고 싶은 한 가지는 docker-compose.yml공개 이미지 (인터넷 / 도커 허브의 이미지 풀링) 만 사용 하면 이미지가 필요하지 않다는 것입니다. 명령을 실행 Dockerfile docker-compose up.
Oldyoung

549

도커 파일

여기에 이미지 설명을 입력하십시오

Dockerfile은 사용자가 이미지를 어셈블하기 위해 호출 할 수있는 명령이 포함 된 간단한 텍스트 파일입니다.

예, Dockerfile

FROM ubuntu:latest
MAINTAINER john doe 

RUN apt-get update
RUN apt-get install -y python python-pip wget
RUN pip install Flask

ADD hello.py /home/hello.py

WORKDIR /home

도커 작성

여기에 이미지 설명을 입력하십시오

도커 작성

  • 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기위한 도구입니다.

  • docker-compose.yml격리 된 환경에서 함께 실행될 수 있도록 앱을 구성하는 서비스를 정의하십시오 .

  • 그냥 실행하여 하나의 명령으로 앱을 실행하십시오. docker-compose up

예, docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}

43
@ sg 대답은 Docker 대 Docker Compose에 대한 이해 부족으로 인해 질문이 잘못 작성되었다는 것입니다. 두 사람의 상호 작용이 아마도 내가 생각할 수있는 최선의 해답 인 간결하게 설명합니다.
mpowered

53
이 정확한 분류가 Docker의 홈페이지에없는 이유를 모르겠습니다. 감사.
codykochmann

4
웹에서 가장 최근에 출시 된 도구 / 솔루션 / 프레임 워크에서 이러한 종류의 문서가 누락되었습니다. 솔루션을 이미 알고 있거나 발명 한 경우 누군가가 왜 필요한지 알기가 어렵습니다.
Peter Branforn

36
이 답변에서 빠진 것은 작성에 대한 자세한 정보입니다. 작성 스크립트가 dockerfile을 호출합니까? 무엇을 구성해야하는지 어떻게 알 수 있습니까? 예제는 표시 image: redis하지만 dockerhub의 것입니까? 로컬 디렉토리? 등등 ... 이것은 나와 같은 새로운 사람이 실제로 무슨 일이 일어나고 있는지 이해하는 것을 혼란스럽게 만듭니다.
Joe Phillips

5
이 응답은 docker compose의 다중 컨테이너 목적을 주장하지만 컨테이너를 실행할 포트를 지정하는 것과 같이 하나의 컨테이너로도 docker compose를 사용하려는 다른 시나리오가 많이 있습니다 (dockerfile afaik에서는 불가능).
팬 소울

99

그만큼 작성 파일은 설명 의 실행 상태 컨테이너를 하는 방법에 대한 세부 사항 떠나, 용기를 구축Dockerfiles을 . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

앱을 정의 할 때 개발 중 Compose 때이 정의를 사용 하여 CI, 스테이징 및 프로덕션과 같은 다른 환경 에서 애플리케이션을 실행할 수 있습니다 . https://docs.docker.com/compose/production/

또한 Compose는 1.11부터 생산 안전으로 간주됩니다https://docs.docker.com/v1.11/compose/production/ 더 이상 https : // docs 와 같은 프로덕션 환경에서 사용하지 말아야한다는 경고가 없으므로 부터 . .docker.com / v1.10 / compose / production / 않습니다.


1
문제를 제기 해 주셔서 감사합니다. 1.11에서 생산 안전을 위해 수정 된 사항을 더 추가 할 수 있습니까?
MA Hossain Tonu

92

docker-compose는 docker-cli와 관련하여 많은 명령을 작성해야합니다.

docker-compose를 사용하면 여러 컨테이너를 동시에 쉽게 시작하고 특정 형태의 네트워킹과 함께 자동으로 연결할 수 있습니다.

docker-compose의 목적은 docker cli로 작동하지만 여러 명령을 훨씬 빨리 발행하는 것입니다.

docker-compose를 사용하려면 이전에 실행중인 명령을 docker-compose.yml파일 로 인코딩해야 합니다.

당신은 그것들을 yaml 파일에 붙여 넣기 만하는 것이 아니라 특별한 문법이 있습니다.

일단 생성되면, docker-compose cli에 파일을 공급해야하며 파일을 구문 분석하고 지정한 올바른 구성으로 모든 다른 컨테이너를 작성하는 것은 cli에 달려 있습니다.

예를 들어, 하나는 redis-server두 번째는 node-app있고 다른 것을 사용하여 만든 컨테이너는 별도의 컨테이너를 갖 습니다.Dockerfile 현재 디렉토리에서를 .

또한 해당 컨테이너를 만든 후 컨테이너에서 로컬 시스템으로 일부 포트를 매핑하여 내부에서 실행중인 모든 항목에 액세스합니다.

따라서 docker-compose.yml파일의 경우 첫 번째 줄을 다음과 같이 시작하려고합니다.

version: '3'

Docker docker-compose에게 사용하려는 버전을 알려줍니다 . 그 후에 다음을 추가해야합니다.

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .

들여 쓰기가 매우 중요합니다. 또한 하나의 서비스에 대해서는 이미지를 잡고 있지만 다른 서비스에 대해서는docker-compose 대해서는 현재 디렉토리 내부를 살펴보고 두 번째 컨테이너에 사용될 이미지를 빌드하도록 지시하고 있습니다.

그런 다음이 컨테이너에서 열려는 다른 모든 포트를 지정하려고합니다.

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .
    ports:
      -

대시, yaml 파일의 대시는 배열을 지정하는 방법입니다. 이 예제에서는 다음 과 같이 8081로컬 컴퓨터 8081에서 컨테이너 로 매핑 합니다 .

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .
    ports:
      - "8081:8081"

따라서 첫 번째 포트는 로컬 시스템이고 다른 포트는 컨테이너의 포트입니다. 혼동을 피하기 위해 두 포트를 구별 할 수도 있습니다.

version: '3'
services:
  redis-server:
    image: 'redis'
  node-app:
    build: .
    ports:
      - "4001:8081"

이와 docker-compose.yml같은 파일 을 개발 하면 본질적으로 동일한 네트워크에서 이러한 컨테이너를 생성하고 원하는 방식으로 서로 통신하고 원하는만큼 정보를 교환 할 수있는 무료 액세스 권한을 갖게됩니다.

두 컨테이너를 사용하여 만들 때 docker-compose포트 선언이 필요하지 않습니다.

이제 내 예제에서는 Nodejs 앱에서 다음과 같은 코드 구성을 수행해야합니다.

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
  host: 'redis-server'
});

위의 예제를 사용하여 사용자가 수행해야 할 특정 구성이있을 수 있음을 docker-compose.yml 하여 프로젝트와 관련된 파일 해야 할 수도 있습니다.

이제 Nodejs 앱으로 작업하고 redis를 사용하고 있다면 Nodejs가 사용하는 기본 포트를 알고 있으므로 다음을 추가하겠습니다.

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
  host: 'redis-server',
  port: 6379
});

Docker는 Node 앱이 redis-server해당 연결을 찾고 실행중인 컨테이너로 리디렉션한다는 것을 알 것입니다.

내내 Dockerfile유일한 것은 다음과 같습니다.

FROM node:alpine

WORKDIR '/app'

COPY /package.json ./
RUN npm install
COPY . .

CMD ["npm", "start"]

따라서 docker run myimage파일 내부의 모든 컨테이너 또는 서비스 인스턴스를 만들기 위해 실행하기 전에 대신 실행할 수 있으며 docker-compose upDocker는 현재 작업 디렉토리를 찾고 이미지를 찾기 때문에 이미지를 지정할 필요가 없습니다.docker-compose.yml 거기에 파일.

전에 docker-compose.yml, 우리는 두 개의 별도의 명령을 처리했다 docker build .하고 docker run myimage, 그러나에 docker-compose세계 당신은 당신이 쓰는 이미지를 재 구축하려는 경우 docker-compose up --build. Docker에게 컨테이너를 다시 시작하되 다시 빌드하여 최신 변경 사항을 얻도록 지시합니다.

따라서 docker-compose여러 컨테이너로 작업하기가 더 쉽습니다. 다음에이 컨테이너 그룹을 백그라운드에서 시작해야 할 수 docker-compose up -d있고 중지 할 수 있습니다 docker-compose down.


13
@Chris이 답변과 승인 된 답변 사이에 3 년 분량의 지식이있는 것처럼 보입니다.
나루토 Sempai

docker-compose up내 상황에서 하나의 서비스 만 사용하는 것이 좋은 이유가 있는지 궁금합니다 . 다른 단어는와 비교할 docker run xxx때 어떤 이점이 docker-compose up있습니까?
atline September

@atline은 단일 컨테이너 사용의 이점에 대한 Pansoul의 stackoverflow.com/a/45549372/3366962 의 답변을 참조하십시오docker-compose
go2null

1
@PaulRazvanBerg 당신 "또는"부분이 맞습니다 (그리고 6379Redis의 기본 포트입니다).
KrishPrabakar

1
docker-compose.yml의 예를 통해 docker-compose에 대한 몇 가지 질문에 대답 할 수있었습니다. 허용 된 답변은 특히 독 노동자를 처음 접하는 사람들에게는 유용하지 않습니다.
maulik13

43

워크 플로에서 시스템의 각 부분에 대해 Dockerfile을 추가하고 각 부분이 개별적으로 실행될 수 있도록 구성합니다. 그런 다음 docker-compose.yml을 추가하여 연결하고 연결하십시오.

가장 큰 장점은 (내 의견으로는) 컨테이너를 연결할 때 이름을 정의하고 컨테이너를이 이름으로 핑할 수 있습니다. 따라서 이름으로 데이터베이스에 액세스 할 수 있으며 db더 이상 IP로 데이터베이스에 액세스 할 수 없습니다.


이름으로 DB에 액세스하는 것에 대해 더 자세히 설명해 주시겠습니까?
Vedran Maricevic.

어느 부분에? docker-compose에서는 서비스를 정의 할 때 이름을 지정하고 구성 할 필요없이 액세스 할 수있는 일반적인 방법이기 때문에 사소한 것입니다. CI에서 네트워크를 만들고이 네트워크에 컨테이너를 만들고 이름을 지정합니다. 그런 다음 컨테이너 내부에서 호스트 이름이 아닌 이름으로 액세스 할 수 있습니다.
n2o

작곡가에서 나는 의미한다. 그래서 작곡가와 IP 대신 내 앱 구성에서 이미지를 연결하면 작곡가 파일에 지정한 이름으로 MySQL을 targer합니까?
Vedran Maricevic.

맞습니다. 링크를 지정할 필요조차 없습니다. 네트워크가 다르게 지정되지 않으면 기본적으로 연결됩니다. 이 예 에서 "web"서비스는 "redis"라는 이름으로 호스트 "redis"를 핑할 수 있습니다.
n2o

37

"더 나은"은 상대적입니다. 그것은 모두 당신의 요구에 달려 있습니다. Docker compose는 여러 컨테이너를 오케스트레이션하기위한 것입니다. 이 이미지가 이미 docker 레지스트리에 있으면 작성 파일에 이미지를 나열하는 것이 좋습니다. 이러한 이미지 또는 다른 이미지를 컴퓨터의 파일로 작성해야하는 경우 Dockerfile에서 해당 이미지를 빌드하는 프로세스를 설명 할 수 있습니다.

Dockerfiles가 Docker Compose에서 사용된다는 것을 이해하지만 다른 이미지에 대해 여러 FROM 명령을 사용하여 하나의 큰 Dockerfile에 모든 것을 넣는 것이 좋은지 확실하지 않습니까?

단일 dockerfile에서 여러 FROM을 사용하는 것은 기능을 제거하라는 제안이 있기 때문에 좋은 생각이 아닙니다. 13026

예를 들어, 데이터베이스를 사용하고 컴퓨터에 응용 프로그램 파일이있는 응용 프로그램을 고정하려면 다음과 같이 작성 파일을 dockerfile과 함께 사용할 수 있습니다

docker-compose.yml

mysql:
  image: mysql:5.7
  volumes:
    - ./db-data:/var/lib/mysql
  environment:
    - "MYSQL_ROOT_PASSWORD=secret"
    - "MYSQL_DATABASE=homestead"
    - "MYSQL_USER=homestead"
  ports:
    - "3307:3306"
app:
  build:
    context: ./path/to/Dockerfile
    dockerfile: Dockerfile
  volumes:
    - ./:/app
  working_dir: /app

도커 파일

FROM php:7.1-fpm 
RUN apt-get update && apt-get install -y libmcrypt-dev \
  mysql-client libmagickwand-dev --no-install-recommends \
  && pecl install imagick \
  && docker-php-ext-enable imagick \
  && docker-php-ext-install pdo_mysql \
  && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

30

Dockerfile과 Docker Compose는 Dockerland에서 서로 다른 두 가지 개념입니다. Docker에 대해 이야기 할 때 가장 먼저 떠오르는 것은 오케스트레이션, OS 레벨 가상화, 이미지, 컨테이너 등입니다. 다음과 같이 각각을 설명하려고합니다.

이미지 : 이미지는 Docker-trusted 레지스트리에 저장된 변경 불가능한 공유 가능 파일입니다. Docker 이미지는 일련의 읽기 전용 레이어로 구성됩니다. 각 레이어는 이미지의 Dockerfile에 제공되는 명령어를 나타냅니다. 이미지는 실행하는 데 필요한 모든 바이너리를 보유합니다.

여기에 이미지 설명을 입력하십시오

컨테이너 : 이미지의 인스턴스를 컨테이너 라고합니다 . 컨테이너는 호스트 OS에서 실행되는 실행 가능한 이미지 바이너리입니다. 실행중인 이미지는 컨테이너입니다.

여기에 이미지 설명을 입력하십시오

Dockerfile : Dockerfile은 모든 명령 / 빌드 지침을 포함하는 텍스트 문서이며, 사용자는 명령 줄을 호출하여 이미지를 어셈블 할 수 있습니다. 이것은로 저장됩니다 Dockerfile. (소문자 'f'에 유의하십시오.)

여기에 이미지 설명을 입력하십시오

Docker-Compose : Compose는 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기위한 도구입니다. Compose를 사용하면 YAML 파일을 사용하여 응용 프로그램 서비스 (컨테이너)를 구성 할 수 있습니다. 그런 다음 단일 명령으로 구성에서 모든 서비스를 작성하고 시작합니다. 작성 파일은로 저장됩니다 docker-compose.yml.


14

소프트웨어 회사의 관리자이고 새로운 서버를 구입했다고 가정 해보십시오. 하드웨어 만

Dockerfile시스템 관리자 에게이 새 서버에 무엇을 설치해야하는지 알려주는 일련의 지침으로 생각하십시오 . 예를 들면 다음과 같습니다.

  • 데비안 리눅스가 필요해
  • 아파치 웹 서버 추가
  • 우리는 postgresql도 필요합니다
  • 자정 사령관을 설치
  • 완료되면 프로젝트의 모든 * .php, * .jpg 등 파일을 웹 서버의 웹 루트 ( /var/www)에 복사하십시오.

반대로, 서버가 다른 세계와 어떻게 상호 작용할 수 있는지docker-compose.yml 시스템 관리자에게 알려주는 일련의 지침으로 생각 하십시오 . 예를 들어

  • 다른 컴퓨터에서 공유 폴더에 액세스 할 수 있습니다.
  • 포트 80은 호스트 컴퓨터의 포트 8000과 동일합니다.
  • 등등.

(이것은 정확한 설명이 아니라 시작하기에 충분합니다.)


4

Dockerfiles는 예를 들어 베어 본 우분투에서 이미지를 빌드하는 것 입니다. 하나의 이미지와 이라는 두 번째 이미지에 mysql호출 mySQL을 추가 할 수 있습니다 .mywordpressmywordpress

YAML 파일 작성은 이러한 이미지를 가져 와서 응집력있게 실행해야합니다. 예를 들어 docker-compose.yml파일에 서비스 요청이있는 경우 db:

services:
   db:
     image: mySQL  --- image that you built.

worpress라는 서비스 :

wordpress: 
    image: mywordpress

그런 다음 mywordpress 컨테이너 내부에서 dbmySQL 컨테이너에 연결하는 데 사용할 수 있습니다 . 이 마술은 도커 호스트가 네트워크 브리지 (네트워크 오버레이)를 생성하기 때문에 가능합니다.


0

공통 공유 코드베이스가있는 Microservices 세계에서 각 Microservice는 Dockerfile루트 수준 (일반적으로 모든 Microservice 외부 및 상위 POM이있는 위치)에서 반면에 docker-compose.yml모든 Microservice를 완전한 앱으로 그룹화하도록 정의합니다 .

귀하의 경우 "Dockerfile"보다 "Docker Compose"가 선호됩니다. "앱"을 생각하십시오. "쓰기"를 생각하십시오.


0

Dockerfile은 이미지를 어셈블하기위한 텍스트 명령이 포함 된 파일입니다.

Docker compose는 다중 컨테이너 환경을 실행하는 데 사용됩니다.

특정 시나리오에서 언급 한 각 기술에 대해 여러 서비스가있는 경우 (reddis를 사용하는 서비스 1, rabbit mq를 사용하는 서비스 2 등) 각 서비스에 대한 Dockerfile과 공통 docker-compose.yml을 실행할 수 있습니다 모든 "Dockerfile"을 컨테이너로 사용합니다.

단일 서비스에서 모두 원한다면 docker-compose가 실행 가능한 옵션입니다.

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