Docker-Compose를 사용하여 여러 명령을 실행하는 방법


500

여러 명령을 순서대로 실행할 수있는 이와 같은 작업을 수행하려고합니다.

db:
  image: postgres
web:
  build: .
  command: python manage.py migrate
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db

답변:


860

알아 낸 다음를 사용하십시오 bash -c.

예:

command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"

여러 줄에서 동일한 예 :

command: >
    bash -c "python manage.py migrate
    && python manage.py runserver 0.0.0.0:8000"

또는:

command: bash -c "
    python manage.py migrate
    && python manage.py runserver 0.0.0.0:8000
  "

6
@Pedram 실제로 bash가 설치된 이미지를 사용하고 있는지 확인하십시오. 일부 이미지는 또한 bash에 직접 경로를 요구할 수도 있습니다./bin/bash
codemaven

5
bash가 설치되어 있지 않으면 sh -c "명령"을 시도해보십시오.
Chaoste

bash로 전달할 때 명령을 따옴표로 묶어야하며 db가 작동했는지 확인하기 위해 "sleep 5"를 슬립해야했지만 그것은 나를 위해 일했습니다.
traday

74
@Chaoste 권장하고 사용 좋아해요 - 알파인 기반 이미지는 실제로 더 떠들썩한 파티가 설치되어 있지 않은 것 sh대신 :[sh, -c, "cd /usr/src/app && npm start"]
플로리안 네스

1
ash고산 에서만 사용할 수도 있습니다 :)
Jonathan

160

별도의 임시 컨테이너에서 마이그레이션과 같은 시작 전 작업을 실행합니다.

db:
  image: postgres
web:
  image: app
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db
  depends_on:
    - migration
migration:
  build: .
  image: app
  command: python manage.py migrate
  volumes:
    - .:/code
  links:
    - db
  depends_on:
    - db

깨끗하고 분리 된 상태를 유지하는 데 도움이됩니다. 고려해야 할 두 가지 :

  1. 올바른 시작 순서를 확인해야합니다 (dependencies_on 사용)

  2. 빌드와 이미지를 사용하여 처음 라운드에 태그를 지정하여 여러 빌드를 피하고 싶습니다. 다른 용기의 이미지를 참조하면


2
이것은 나에게 가장 좋은 옵션 인 것 같습니다. 사용하고 싶습니다. 여러 빌드를 피하기 위해 태그 설정을 정교하게 할 수 있습니까? 추가 단계를 피하기를 원하므로 이것이 필요한 경우 bash -c위와 같이 갈 수 있습니다 .
Stavros Korokithakis

3
위의 yaml에서 빌드 및 태깅은 마이그레이션 섹션에서 발생합니다. 언뜻보기에는 분명하지 않지만, 빌드 및 이미지 속성을 지정할 때 docker-compose가 태그를 지정합니다. 이미지 속성은 해당 빌드의 태그를 지정합니다. 그런 다음 새 빌드를 트리거하지 않고 나중에 사용할 수 있습니다 (웹을 보면 빌드가 아니라 이미지 속성 만 있음). 여기에 좀 더 세부 사항의 docs.docker.com/compose/compose-file )
비욘 Stiel

26
나는 이것의 아이디어를 좋아하지만, 문제는 depend_on이 순서대로 준비되지 않고 순서대로 시작한다는 것입니다. wait-for-it.sh는 일부 사람들에게 필요한 솔루션 일 수 있습니다.
traday

2
그것은 절대적으로 정확하며 docker-compose는 컨테이너가 종료되거나 포트에서 청취를 시작하는 것과 같은 미세한 제어를 지원하지 않습니다. 그러나 그렇습니다. 맞춤 스크립트는 이것을 해결합니다.
Bjoern Stiel

1
이 답변은 depend_on 작동 방식에 대한 부정확하고 파괴적인 정보를 제공합니다.
antonagestam

96

대부분의 유닉스 기반 이미지 (알파인 등)에서 더 쉽게 사용할 수 있기 때문에 sh반대로 사용 하는 것이 좋습니다 bash.

예를 들면 다음과 같습니다 docker-compose.yml.

version: '3'

services:
  app:
    build:
      context: .
    command: >
      sh -c "python manage.py wait_for_db &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"

다음 명령을 순서대로 호출합니다.

  • python manage.py wait_for_db -DB가 준비 될 때까지 기다립니다.
  • python manage.py migrate -모든 마이그레이션을 실행
  • python manage.py runserver 0.0.0.0:8000 -개발 서버를 시작하십시오

2
개인적으로 이것은 내가 가장 좋아하는 가장 깨끗한 솔루션입니다.
BugHunterUK

1
내 것도. @LondonAppDev가 지적했듯이 공간에 최적화하기 위해 모든 컨테이너에서 기본적으로 bash를 사용할 수 없습니다 (예 : 알파인 리눅스 위에 구축 된 대부분의 컨테이너)
ewilan

2
나는 \와 함께 여러 줄을 && 탈출해야했습니다
Andre Van Zuydam

@AndreVanZuydam hmmm 그것은 이상합니다, 나는 그렇게 할 필요가 없었습니다. 따옴표로 묶었습니까? 어떤 종류의 도커를 사용하고 있습니까?
LondonAppDev

2
@oligofren은 >멀티 라인 입력을 시작하는 데 사용됩니다 ( stackoverflow.com/a/3790497/2220370 참조 )
LondonAppDev

40

이것은 나를 위해 작동합니다 :

version: '3.1'
services:
  db:
    image: postgres
  web:
    build: .
    command:
      - /bin/bash
      - -c
      - |
        python manage.py migrate
        python manage.py runserver 0.0.0.0:8000

    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

docker-compose는 명령을 실행 하기 전에 변수를 역 참조하려고 시도 하므로 bash에서 변수를 처리하려면 달러 기호를 두 배로 늘려야합니다.

    command:
      - /bin/bash
      - -c
      - |
        var=$$(echo 'foo')
        echo $$var # prints foo

... 그렇지 않으면 오류가 발생합니다.

"web"서비스의 "command"옵션에 대한 잘못된 보간 형식 :


안녕 친구. ```인식 할 수없는 인수 : / bin / bash -c python3 /usr/local/airflow/__init__.py -C Local -T Windows```내 docker-compose.yml의 명령은 다음과 같습니다. -/ bin / bash--c-| python3 /usr/local/airflow/__init__.py -C $ {Client} -T $ {Types} 그 문제를 해결하는 방법을 알고 있습니까? 내 .env 파일에 클라이언트 및 유형을 추가합니다.
Newt

: 여기 당신을위한 문서입니다 docs.docker.com/compose/compose-file/#variable-substitution가 나는 것을 일어나는 것은 당신의 .env의 파일이 컨테이너 환경에서 그 변수를 배치한다는 것입니다 생각하지만, 고정 표시기-작성은 쉘 환경에서 찾고 . 대신 시도 $${Types}하고 $${Client}. 이것은 docker compose가 변수를 해석하고 docker-compose를 호출하는 모든 쉘에서 값을 찾는 것을 막을 것이라고 생각합니다. 즉, docker가 파일 을 처리 한 후 bash가 변수를 역 참조 할 수 .env있습니다.
MatrixManAtYrService

귀하의 의견에 감사드립니다. 당신이 실제로 한 말을 했어요 그래서 오류 정보에 $ (Client)가 있습니다. 파이썬에서 os.getenv를 사용하도록 환경 변수를 읽는 방법이 변경되었습니다. 어쨌든 고마워
Newt

23

여기에서 진입 점을 사용할 수 있습니다. docker의 진입 점은 명령 전에 실행되는 반면 command는 컨테이너가 시작될 때 실행되어야하는 기본 명령입니다. 따라서 대부분의 응용 프로그램은 일반적으로 진입 점 파일에 설정 절차를 수행하며 마지막에는 명령 실행을 허용합니다.

쉘 스크립트 파일 docker-entrypoint.sh을 다음 내용과 같이 (이름은 중요하지 않음)로 만들 수 있습니다 .

#!/bin/bash
python manage.py migrate
exec "$@"

docker-compose.yml 파일에서 그것을 사용 entrypoint: /docker-entrypoint.sh하고 command: python manage.py runserver 0.0.0.0:8000 PS로 명령을 등록 docker-entrypoint.sh하십시오 : 코드와 함께 복사하는 것을 잊지 마십시오 .


당신이 할 때이 또한 실행하는 것을 주docker-compose run service-name ....
thisismydesign

18

또 다른 아이디어 :

이 경우와 같이 컨테이너를 빌드하면 시작 스크립트를 배치하고 명령으로 실행하십시오. 또는 시작 스크립트를 볼륨으로 마운트하십시오.


예, 마지막에 run.sh 스크립트를 만들었습니다 : #!/bin/bash \n python manage.py migrate \n python manage.py runserver 0.0.0.0:8000(ugly oneline)
fero

9

* 업데이트 *

일부 명령을 실행하는 가장 좋은 방법은 공식 CMD가 이미지에서 실행되기 전에 원하는 모든 작업을 수행하는 사용자 정의 Dockerfile을 작성하는 것입니다.

docker-compose.yaml :

version: '3'

# Can be used as an alternative to VBox/Vagrant
services:

  mongo:
    container_name: mongo
    image: mongo
    build:
      context: .
      dockerfile: deploy/local/Dockerfile.mongo
    ports:
      - "27017:27017"
    volumes:
      - ../.data/mongodb:/data/db

Dockerfile.mongo :

FROM mongo:3.2.12

RUN mkdir -p /fixtures

COPY ./fixtures /fixtures

RUN (mongod --fork --syslog && \
     mongoimport --db wcm-local --collection clients --file /fixtures/clients.json && \
     mongoimport --db wcm-local --collection configs --file /fixtures/configs.json && \
     mongoimport --db wcm-local --collection content --file /fixtures/content.json && \
     mongoimport --db wcm-local --collection licenses --file /fixtures/licenses.json && \
     mongoimport --db wcm-local --collection lists --file /fixtures/lists.json && \
     mongoimport --db wcm-local --collection properties --file /fixtures/properties.json && \
     mongoimport --db wcm-local --collection videos --file /fixtures/videos.json)

아마도 가장 깨끗한 방법 일 것입니다.

* 구식 *

명령으로 쉘 스크립트를 만들었습니다. 이 경우 시작 mongod하고 싶었지만 mongoimport전화를 mongod걸면 나머지는 실행되지 않습니다.

docker-compose.yaml :

version: '3'

services:
  mongo:
    container_name: mongo
    image: mongo:3.2.12
    ports:
      - "27017:27017"
    volumes:
      - ./fixtures:/fixtures
      - ./deploy:/deploy
      - ../.data/mongodb:/data/db
    command: sh /deploy/local/start_mongod.sh

start_mongod.sh :

mongod --fork --syslog && \
mongoimport --db wcm-local --collection clients --file /fixtures/clients.json && \
mongoimport --db wcm-local --collection configs --file /fixtures/configs.json && \
mongoimport --db wcm-local --collection content --file /fixtures/content.json && \
mongoimport --db wcm-local --collection licenses --file /fixtures/licenses.json && \
mongoimport --db wcm-local --collection lists --file /fixtures/lists.json && \
mongoimport --db wcm-local --collection properties --file /fixtures/properties.json && \
mongoimport --db wcm-local --collection videos --file /fixtures/videos.json && \
pkill -f mongod && \
sleep 2 && \
mongod

따라서이 몽고 포크, monogimport를 수행 한 다음 분리 된 포크 몽고를 죽이고 분리하지 않고 다시 시작합니다. 분기 프로세스에 연결하는 방법이 있는지 확실하지 않지만 작동합니다.

참고 : 일부 초기 DB 데이터를 엄격하게로드하려면 다음과 같이하십시오.

mongo_import.sh

#!/bin/bash
# Import from fixtures

# Used in build and docker-compose mongo (different dirs)
DIRECTORY=../deploy/local/mongo_fixtures
if [[ -d "/fixtures" ]]; then
    DIRECTORY=/fixtures
fi
echo ${DIRECTORY}

mongoimport --db wcm-local --collection clients --file ${DIRECTORY}/clients.json && \
mongoimport --db wcm-local --collection configs --file ${DIRECTORY}/configs.json && \
mongoimport --db wcm-local --collection content --file ${DIRECTORY}/content.json && \
mongoimport --db wcm-local --collection licenses --file ${DIRECTORY}/licenses.json && \
mongoimport --db wcm-local --collection lists --file ${DIRECTORY}/lists.json && \
mongoimport --db wcm-local --collection properties --file ${DIRECTORY}/properties.json && \
mongoimport --db wcm-local --collection videos --file ${DIRECTORY}/videos.json

mongo_fixtures / *. json 파일은 mongoexport 명령을 통해 작성되었습니다.

docker-compose.yaml

version: '3'

services:
  mongo:
    container_name: mongo
    image: mongo:3.2.12
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db:cached
      - ./deploy/local/mongo_fixtures:/fixtures
      - ./deploy/local/mongo_import.sh:/docker-entrypoint-initdb.d/mongo_import.sh


volumes:
  mongo-data:
    driver: local

5

둘 이상의 데몬 프로세스를 실행 해야하는 경우 Docker 설명서에 Supervisord 를 분리되지 않은 모드 로 사용하라는 제안이 있으므로 모든 하위 데몬이 stdout으로 출력됩니다.

다른 SO 질문에서 하위 프로세스 출력을 stdout으로 리디렉션 할 수 있음을 발견했습니다. 그렇게하면 모든 출력을 볼 수 있습니다!


이것을 다시 보면이 대답은 직렬 대신 여러 명령을 병렬로 실행하는 데 더 적합합니다.
Tim Tisdall


1

wait-for-it 또는 dockerize 와 같은 도구를 사용하십시오 . 이들은 작은 래퍼 스크립트이며 응용 프로그램 이미지에 포함 할 수 있습니다. 또는 고유 한 랩퍼 스크립트를 작성하여 더 많은 응용 프로그램 특정 명령을 수행하십시오. https://docs.docker.com/compose/startup-order/ 에 따르면


0

jenkins 컨테이너를 jenkins 사용자로 도커 컨테이너를 빌드하도록 설정하는 동안이 문제가 발생했습니다.

나중에 docker-compose 파일에서 링크 할 때 Dockerfile의 docker.sock 파일을 터치해야했습니다. 내가 먼저 만지지 않으면 아직 존재하지 않았습니다. 이것은 나를 위해 일했습니다.

도커 파일 :

USER root
RUN apt-get update && \
apt-get -y install apt-transport-https \
ca-certificates \
curl \
software-properties-common && \
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; 
echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) \
stable" && \
apt-get update && \
apt-get -y install docker-ce
RUN groupmod -g 492 docker && \
usermod -aG docker jenkins  && \
touch /var/run/docker.sock && \
chmod 777 /var/run/docker.sock

USER Jenkins

docker-compose.yml :

version: '3.3'
services:
jenkins_pipeline:
    build: .
    ports:
      - "8083:8083"
      - "50083:50080"
    volumes:
        - /root/pipeline/jenkins/mount_point_home:/var/jenkins_home
        - /var/run/docker.sock:/var/run/docker.sock

이것은 다른 질문에 대한 답변처럼 보입니다.
kenorb

-7

";"을 사용해보십시오 verions two에있는 경우 명령을 분리합니다. 예 :

command: "sleep 20; echo 'a'"

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