본문 바로가기
협업툴,가상환경 정리/docker_정리

docker compose 설명

by 알 수 없는 사용자 2022. 9. 23.

참고

https://meetup.toast.com/posts/277

 

Docker Compose와 버전별 특징 : NHN Cloud Meetup

도커는 이제 대부분의 개발자 노트북이나 PC에 하나씩은 설치되어있는 필수품이 되어가는데요 편하고 유용한 도커를 좀 더 유익하고 편하게 사용할 수 있는 도구인 Docker Compose에 대해서 알기 쉽

meetup.toast.com

 

https://wonhyeok1994.tistory.com/194?category=1057888 

 

도커 볼륨 vs 바인드 마운트

참고 : https://www.dltlabs.com/blog/bind-mounts-volumes-indocker-133067 Bind Mounts & Volumes in Docker We share the fundamentals of Docker and tell you how Bind Mounts and Volumes work. www.dltlab..

wonhyeok1994.tistory.com

 

도커한테 PEP 사이트 같은곳 성지 ( 사실 여기보고 하면 다됨

https://docs.docker.com/compose/compose-file/compose-file-v3/#image

 

Compose file version 3 reference

 

docs.docker.com

 

이렇게 찾아보면됨

필요한건 읽어서 찾고

 

 


Dockerfile과 docker-compose의 주요 차이점은

 

Dockerfile은 Docker 이미지 를 빌드 하는 방법을 설명하는 반면

docker-compose는 Docker 컨테이너 를 실행 하는 데 사용된다는 것입니다.

Dockerfile의 내용은 Docker 이미지를 만들고 빌드하는 방법을 설명하는 반면 

docker-compose는 docker-compose.yaml 파일 에 설명된 설정을 기반으로 Docker 컨테이너를 실행하는 명령입니다 

 

또 하나의 특징은 docker run ~~~ 로 하나씩 컨테이너를 키는게 아니라 'docker-compose'로 다중 컨테이너 실행이 가능한 점이다.


docker-compose 관련 명령어

 

1.

up

docker-compose.yml 파일의 내용에 따라 이미지를 빌드하고 서비스를 실행합니다.

$ docker-compose -p nhn up -d
Creating network "nhn_default" with the default driver
Creating nhn_mysql_1 ... done
Creating nhn_app_1   ... done

up 명령어로 compose를 실행 시의 단계별 진행사항은 다음과 같습니다.

  1. 서비스를 띄울 네트워크 설정
  2. 필요한 볼륨 생성(혹은 이미 존재하는 볼륨과 연결)
  3. 필요한 이미지 풀(pull)
  4. 필요한 이미지 빌드(build)
  5. 서비스 의존성에 따라 서비스 실행

options

  • -d: 서비스 백그라운드로 실행. (docker run에서의 -d와 같음)
  • --force-recreate: 컨테이너를 지우고 새로 생성.
  • --build: 서비스 시작 전 이미지를 새로 생성
  • -f: 기본으로 제공하는 docker-compose.yml이 아닌 별도의 파일명을 실행할 때 사용
  • docker-compose -f docker-compose.yml -f docker-compose-test.yml up 형태로 두 개의 파일 실행도 가능
  • YAML을 두 개 이상 설정할 경우 앞에 있는 설정보다 뒤에 있는 파일이 우선

 

 

2. 

down

실행 중인 서비스를 삭제합니다.
컨테이너와 네트워크를 삭제하며, 옵션에 따라 볼륨도 같이 삭제할 수 있습니다.

$ docker-compose down
Stopping nhn_mysql_1 ... done
Removing nhn_app_1   ... done
Removing nhn_mysql_1 ... done
Removing network nhn_default

options

  • -v, --volume: 볼륨까지 같이 삭제
    • DB 데이터 초기화하는데 용이함
    • 모든 설정을 초기화하고 새로 시작하는 데 사용

 

3.

stop, start

서비스를 멈추거나, 멈춰 있는 서비스를 시작합니다.

$ docker-compose stop
Stopping nhn_mysql_1 ... done

$ docker-compose start
Starting app   ... done
Starting mysql ... done

 

4.

ps

현재 환경에서 실행 중인 각 서비스의 상태를 표시합니다.

   Name                  Command               State           Ports
---------------------------------------------------------------------------
nhn_app_1     docker-entrypoint.sh sh -c ...   Exit 1
nhn_mysql_1   docker-entrypoint.sh mysqld      Up       3306/tcp, 33060/tcp

 

5.

exec

실행 중인 컨테이너에서 명령어를 실행합니다.

명령어는 다음과 같은 패턴으로 실행됩니다.
docker-compose exec {정의한 service name} {실행될 명령어}

$ docker-compose exec app ./upload_logs.sh

$ docker-compose exec mysql mysql -uroot -psecret todos

$ docker-compose exec -t gitlab-runner gitlab-runner register 

docker-compose exec -t <컨테이너명> <명령어>

 

6. 

logs

output으로 나온 log들을 확인할 때 사용합니다.
docker의 logs와 마찬가지로 --follow(혹은 -f)를 하여 실시간으로 나오는 로그 확인이 가능합니다.

$ docker-compose logs -f
Attaching to docker_app_1, docker_mysql_1
app_1    | yarn install v1.22.5
app_1    | info No lockfile found.
app_1    | [1/4] Resolving packages...
app_1    | [2/4] Fetching packages...
app_1    | [3/4] Linking dependencies...
app_1    | [4/4] Building fresh packages...
app_1    | success Saved lockfile.
app_1    | Done in 0.14s.
app_1    | yarn run v1.22.5
app_1    | error Couldn't find a package.json file in "/app"
app_1    | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

 

7. 이건 짧게 말해서  환경변수 등록해서 user: "$(UID):$(GID)" 이런식으로 쓸 수 있단 얘기

Docker Compose Environment

docker compose의 장점으로는 하나를 정의해놓으면 여러 군데서 동일한 동작을 보장하는 것입니다.
하지만 각 실행 환경에 따라 변경되어야 하는 옵션들이 있는데 이것들 때문에 일일이 파일을 수정하는 건 비효율적입니다.
그래서 각 실행하는 환경마다 환경변수 파일을 정의하여 동일한 compose 파일로 각각의 환경과 동적인 옵션으로 실행이 가능합니다.

. env file

기본적으로 docker-compose up을 한 상태에서 . env 파일을 찾아 파일 내부에 있는 값을 환경 변수로 사용합니다.

$ cat .env     # 환경변수 파일
TAG=v1.5

$ cat docker-compose.yml   # compose 파일
version: '3'
services:
  web:
    image: "webapp:${TAG}"$

$ docker-compose config    # 실제 적용된 옵션

version: '3'
services:
  web:
    image: 'webapp:v1.5'


$ export TAG=v2.0
$ docker-compose config

version: '3'
services:
  web:
    image: 'webapp:v2.0'

여러 파일에서 동일한 환경 변수를 설정할 때 사용할 값을 선택하기 위해 Compose에서 사용하는 우선순위는 다음과 같습니다.

  1. Compose file
  2. Shell environment variables
  3. Environment file
  4. Dockerfile
  5. Variable is not defined

여러 개의 복잡합인 상황에 따라서 의도하지 않은 설정이 들어가지 않게 우선순위를 잘 파악해보는 것이 중요합니다.

상황에 따른. env 적용 예제

dev, prod, local 환경에 따라서
.env.dev, .env.prod, .env.local 형식으로 할당을 줄 수 있는데
--env-file 옵션으로 환경변수 파일 지정이 가능합니다.

$ docker-compose --env-file ./config/.env.dev up

CLI Environment

아래의 명령어들은 각각 그 아래의 compose 파일이 일치하게 맵핑됩니다.

$ docker run -e VARIABLE1

web:
  environment:
    - VARIABLE1
$ docker-compose run -e DEBUG=1 web python console.py

web:
  environment:
    - DEBUG=1

Docker Cli Environment Variable

Compose CLI에서 실행할 때의 참고 변수 키 값 정의가 가능합니다.
https://docs.docker.com/compose/reference/envvars/

 

Compose CLI environment variables

 

docs.docker.com

 

 

 


docker-compose 

yaml 파일 주 구성

1.

version: 

도커 파일 포멧에 대한 내용임. ( Docker Engine 버전과도 관계가 있다. ), 버전따라 services나 특징들이 조금씩 다름

2.

network:

"docker network ls" 에서 나오는 network와 연결

3.

volumes:

도커는 볼륨과 바인드 마운트 개념이 있는데 여기서 volumes: 에 내용은 도커 볼륨 기능

4.

services:

실행하려는 컨테이너들을 정의.

컨테이너를 실행 시킬때 여러 설정값 config 값, 어떤 이미지를 쓸지, 이름은 뭐할지, 바인드마운트 경로는 어디로 할지 에 대한 내용을 정의 해주는 구간. ( 컴포즈에서 가장 핵심적인 구성이다. )

 

 

짧게 yaml 문법 :

key:val 구조이고

# 이 주석

val 를 한칸 내려서 쓸 때는 '-' 를 사용

 

yaml 코드 구조 예시:

1.

key : val

2.

key :

  key : val

3.

key :

  key : val

  key : val

  key:

    - val

    - val

    - val

4.

key :

  key : val

    entrypoint: >
      bash -c '
      chmod 777 ./docker_files/* &&
      source /app/docker_files/ros_entrypoint.sh &&
      source /app/docker_files/run_colcon.sh &&
      source /app/docker_files/start_server.sh &&
      source /app/docker_files/sleep_to_delay_closing_time.sh
      '

 


간단한 예시 랑 각 옵션별 설명

 

2. network 관련

예를들어 "docker network create --gateway 172.29.0.1 --subnet 172.29.0.0/21 --driver bridge custom_network_bridge"

라고 커스텀 네트워크를 만들었으면 

networks:
    custom_network_bridge:
        driver: custom_network_bridge

        external: true 

external 설명 -> default 값은 false 이다. true 로 지정시, network를 따로 생성하지 않고 외부에 생성되있는 network 를 검색해서 사용한다. ( 따라서 외부에 없는 네트워크를 쓰려고 하면 에러남 )

 

------------------------

networks:
  custom_network_bridge:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.99.0.0/21
          gateway: 172.99.0.1

이렇게 커스텀 네트워크를 docker-compose로 구성후,

networks:
    custom_network_bridge:
        driver: custom_network_bridge
        external: true

이렇게 pre_existing_network 기존에 미리 생성한 네트워크에 물릴 수 있다.

 

 

3. volumes: 관련

"docker volume create backup-storage" 이 명령어로 볼륨 생성을 한 후 docker-compose에서 지정해서 쓸 수 있다.

밑에 처럼 쓰면 됨. 

volumes:
  server_backup_volume:
    name: backup-storage
    driver: local

 

 

4. services: 관련

 

  container_name_2:
    image: 사용할 이미지
    container_name: 컨테이너 이름(컨테이너간 통신에서 쓰인다,)
    hostname: 도커 컨테이너 CLI 창에서 'hostname' 치면 이거나옴
    extra_hosts: "/etc/hosts" 에 "192.168.65.2    host.docker.internal"를 추가해준다. docker_host 의 localhost를 IP를 추적한다.
    environment: 환경변수 저장
    ports: 호스트 OS와 컨테이너의 포트를 바인딩 시킴.  ex) HOST:CONTAINER  "8080:8080"

    expose: ports와 개념은 같지만 호스트 내부의 다른 컨테이너들만 액세스 가능하게  하는 방법 ex) "8080"
    sysctls: 커널관련 파라미터 세팅
    command: dockerfile 에서 RUN 개념
    entrypoint: dockerfile 에서 ENTRYPOINT 개념      

    network_mode: 'host' 이렇게 직접 docker network를 사용
    volumes: "docker volume create backup-storage" 이거로 생성한 볼륨이나 'Mount host paths'를 볼륨으로 지정 가능
    restart: 컨테이너 종료시 재시작 자동으로 할지
    working_dir: 컨테이너 접속시 시작 디렉터리
    depends_on: 컨테이너 이름을 지정해서 의존성을 엮을 수 있다. 컨테이너 생성 순서 관여됨

    build:
      context: Dockerfile이 포함된 디렉토리의 경로 또는 git 리포지토리 URL
      dockerfile: context에 있는 도커파일 이름을 지정

      args:
        buildno: 빌드 넘버 

    networks: "network:" 에서 설정한 network들을 별칭으로 사용
      custom_network_bridge: <- 이렇게 별칭으로 사용 
        ipv4_address: 172.29.0.22  <- 해당 네트워크에 고정 IP 주소로 할당

      custom_network_bridge: 
    user:
      app-tier:
        aliases:
    logging:
      driver: "json-file"
      options:
        max-file: "1"
        max-size: "100m"

 

 


도커 명령어 실행 VS docker-compose 실행

비교

 

도커 명령어 :

$ docker run -dp 3000:3000 \
  -w /app -v ${PWD}:/app \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:12-alpine \
  sh -c "yarn install && yarn run dev"

이걸 docker-compose로 변환하면 

version: "3.8"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

이렇게 됨.

 


도커 명령어 :

$ docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:5.7

이걸 docker-compose로 변환하면 

version: "3.8"

services:
  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

이렇게 됨.


다른 docker-compose 예시 

  test_container:
    image: ${CONT_DOCKER_IMAGE}
    container_name: test_container
    hostname: test_container
    working_dir: $DOCKER_CONT_PATH/
    user: "${USER_ID}:${GROUP_ID}"				# 도커 내부에서 root 가 아닌 특정 유저로 접속
    environment:
      - LANG=C.UTF-8
      - LC_ALL=C.UTF-8
      - USER_NAME=$USER_NAME
      - HOME=$DOCKER_HOME						# docker_host의 HOME 과 동일시
#      - DISPLAY=$DISPLAY                       # X11 관련 설정 ( OS가 우분투 일 경우 )
      - DISPLAY=host.docker.internal:0.0        # X11 관련 설정 ( OS가 Windows + docker-descktop 일 경우 )
      - LIBGL_ALWAYS_INDIRECT=0                 # X11 관련 설정 ( OS가 Windows + docker-descktop 일 경우 )
      - ROS_MASTER_URI=http://${NETWORK_ABC_CLASS}.${ROSCORE_IP}:${ROSCORE_PORT}   # ROSCORE 주소 설정 MASTER URI
      - ROS_IP=${NETWORK_ABC_CLASS}.${CONT_IP}                        # ROSCORE 주소 설정 본인 IP
    networks:
      test_templete_network:
        ipv4_address: "${NETWORK_ABC_CLASS}.${CONT_IP}"
    ports:
      - '200${CONT_IP}:22'  # 외부 포트는 2002 실제 내부로 접속되는건 22 // 포트포워딩
      - '10005:10005'
    volumes:
      - /etc/passwd:/etc/passwd					# docker_host의 유저 PW정보를 동기화
      - /etc/group:/etc/group					# docker_host의 유저 그룹정보를 동기화
      - /etc/sudoers.d:/etc/sudoers.d			# docker_host에도 되어 있어야 하는 부분 : 도커 컨테이너 내에서 sudo시 비밀번호 입력하지 않고 가능하게끔
      - /etc/shadow:/etc/shadow					# docker_host의 유저관련해서 암호화된 폴더를 동기화
      - /tmp/.X11-unix:/tmp/.X11-unix            # X11 관련 설정 ( OS가 우분투 일 경우 )
      - /etc/localtime:/etc/localtime
      - $HOST_DOCKER_FILES_VOLUME_PATH:$DOCKER_DOCKER_FILES_VOLUME_PATH  # 공용 : 도커파일즈
      - $HOST_SHARE_VOLUME_PATH:$DOCKER_SHARE_VOLUME_PATH  # 공용 : 쉐어 디렉토리
      - $HOST_CONT_PATH:$DOCKER_CONT_PATH  # 실제 작업공간
    restart: ${RESTART}
    extra_hosts:
      - host.docker.internal:host-gateway		# docker_host의 local_host IP를 "/etc/hosts"에 추가해준다. 따라서 local_host는 컨테이너의 localhost이고 host.docker.internal는 docker_host의 localhost이다.
    entrypoint: >
      bash -c '
      sudo touch $HOME/.bashrc &&
      sudo chown -R $USER_NAME:$USER_NAME $HOME &&
      sudo chown -R $USER_NAME:$USER_NAME $HOME/.bashrc &&
      source $CONT_ENTRYPOINT_PATH &&
      sleep 3
      '

 


도커 컨테이너간 통신

방법은 2개

1. 포트 포워딩

2. 같은 네트워크 대역으로 편입시켜서 직접 바라보게끔 

 

1. 포트 포워딩

https://learn.microsoft.com/ko-kr/dotnet/architecture/microservices/multi-container-microservice-net-applications/multi-container-applications-docker-compose

 

docker-compose.yml을 사용하여 다중 컨테이너 애플리케이션 정의

docker-compose.yml을 사용하여 다중 컨테이너 애플리케이션에 대한 마이크로 서비스 컴퍼지션을 지정하는 방법입니다.

learn.microsoft.com

 

2. custom network 를 만들어서 "docker network inspect 커스텀네트워크이름" 안의 "Containers" 에 포함되게끔 IP 대역대를 편입시킨 후, 직접 IP를 바라보고 동작시키면 된다.

 

 


services 에서

entrypoint

run

command

사용할 때 팁 

1. 따로따로 linux 명령어 치는 것보다  " aa && bb && cc " 이런 식으로 구동할 것.

2. 쉘 명령어 쓸때 $@, $? 등 쓰려면 $ -> $$ 이런식으로 2번 써야 인식함. 

3. > bask -c ' ~~~ ' 구성을 이용하면 리눅스랑 동일한 구조로써 사용 가능.

 

예제 1:

entrypoint: >
  bash -c '
  chmod 777 /app/docker_files/* &&
  source /app/docker_files/ros_entrypoint.sh &&
  source /app/docker_files/run_colcon.sh &&
  source /app/docker_files/start_server.sh &&
  source /app/docker_files/sleep_to_delay_closing_time.sh
  '

 

 

예제 2:

entrypoint: >
  /bin/bash -c '
  for (( ; ; ))
  do
    sleep 1
    $$CMD 명령어_1
      if [ $$? -eq 0 ];   	# <- 명령어_1 이 성공 했으면
      then
        echo "SUCCESS "
        $$CMD 명령어_2
        sleep 1
        break
      else					# <- 명령어_1 이 실패 했으면
        echo "FAILE "
        sleep 1
        break
      fi
    echo 'asdasd'
  done
  '

 


global variable

yaml 파일 에서는  

이런식으로 variables: ~~ 하고

$(키값) 이런식으로 쓰면된다.

 

하지만 docker-compose에서는 저렇게 못쓴다.

docker-compose 에서 쓰는 방법은 ".env" 라는 파일을 만들어 global variable(TAG) 를 지정하고

docker-compsoe 에서 ${키값} 으로 가져오면 된다.

예시 : 

1. env ( docker-compose 있는 디렉토리에 저장 ) 예시 :

 

2.  docker-compose 활용 예시 :  이런식으로도 활용이 가능함.

 

 

댓글