Search

Docker Compose

Docker compose

두개이상의 컨테이너를 띄우기 위한 기술.
앱의 요구를 처음 받아주는 것을 백엔드 또는 load balancer라고 함. 뒤에 있는 누군가에게 선택해서 전달하기 때문에 dispatcher라고도 부르고 reverse proxy, service gateway라고도 함.
정보를 지금 만들어서 보여줘야하는경우 intelligence service에서 작업을 수행하고 결과를 보내준다.
http서버, static한 정보를 저장하는 database, 입력 받아서 로직을 수행하는 intelligent service
이 각각을 컨테이너로 구축한다.
필요할때 필요한만큼 컨테이너 수를 추가하거나 삭제한다 = scaling.
두 개 이상의 컨테이너를 만드는 tool이 docker compose다.
A tool for defining and running multi-container docker applications
docker-compose.yml = docker compose configuration file

Docker compose 명령어

docker compose up
docker compose down (시스템 죽인다)
docker compose up —scale (특정 컨테이너가 용량 부족해서 더 키워야 하는 경우)
docker compose는 별도로 설치해야하는 프로그램이었는데 지금은 docker desktop에 포함된다.
nginx웹서버와 redis 데이터베이스를 한꺼번에 띄운다. web서비스 하나와 database서비스 하나.
depends_on: db는 db가 구동되어야 구동할 수 있는 선후관계가 있는것.
이미지를 먼저 구동했다는거니 서버가 구동이 되어 ready상태라는것과는 다르게 client가 나중에 구동됐는데 먼저 실행되어서 에러가 나는 경우도 존재할 수 있다. 이미지 띄우는 순서일 뿐이다.
restart:always 죽으면 바로 다시 실행
volumes: 스토리지
compose버전은 써도되고 안써도 된다.
이미지 만들었고 docker compose파일 만들었으면 docker compose up -d로 docker run처럼 실행한다.
docker compose up -d 명령어에서 -d는 "detached" 모드를 의미한다. 이 모드를 사용하면 Docker 컨테이너가 백그라운드에서 실행되며, 터미널을 다른 작업에 사용할 수 있게 된다.
컨테이너 이름에 -1이 붙는다. 현재폴더-이미지 이름-인덱스 순으로 명칭이 붙음.
network created라는 문장을 확인할 수 있는데 웹과 데이터베이스 컨테이너가 물리적으로 같은 네트워크에 물려있는것처럼 가상의 네트워크 사용한다.
docker compose config
yml파일에 있는 configuration을 보여준다.
docker compose config —service 처럼 일부만 볼 수 있다.
docker stats 도커 컨테이너 통계치 보여줌
docker compuse up을 실행하는 위치는 yml파일이 있는 곳이다.
docker compose down을 실행하면 네트워크를 지우고 컨테이너를 내린다.
이미지는 아직 남아있으므로 rm으로 지우는것이 좋다.
컨테이너는 별도의 공간이라 포트매핑이 필요하다.
8000:80은 외부 8000번을 컨테이너 내부 80번으로 매핑해달라는 뜻이다.
포트매핑은 외부에 있는 포트를 내부에 있는 포트로 매핑하는 PAT기능이다
PAT: Port Address Translation
NAT: Network Address Translation
여기서의 inside 네트워크의 상태가 컨테이너 내부와 비슷하다. 컨테이너는 여러개가 하나의 물리적인 네트워크로 구성되어있으며 컨테이너들을 연결하는 가상의 네트워크가 구축되어있다. 컨테이너 내부와 외부환경을 연결하는것이 포트매핑이다. 쿠버네티스에서는 이 컨테이너를 감싸는 가상의 네트워크를 pod이라고 한다.

YAML

ml = markup language 사람이 눈으로 읽어서 이해할수있는 기호로 이루어진 언어.
yaml은 data serialization language이다. 데이터 직렬화란 바이트 스트림으로 변환하는것을 말한다. 스트림은 연속적인 데이터의 흐름을 말한다.
예를 들어 C++의 cin은 키보드에서 입력된 정보의 input stream 과정은 키보드 입력이 serial cable을 따라서 바이트로 이동해서 C++프로그램으로 전달되는것이다. cout의 경우 내 프로그램에서 모니터로 데이터스트림, 즉 바이트가 흘러간다.
키보드에서 입력된 정보를 콘솔 인풋 스트림 serial cable을 따라서 바이트로 이동해서 c++프로그램으로 간다
cout하면 내 프로그램에서 모니터로 데이터 스트림 즉 바이트가 흘러간다 데이터를 입출력하는 과정은 스토리지에서 바이트 스트림을 받아와서 프로그램의 메모리에 담는 것이고 스토리지에 저장할때도 바이트 스트림으로 저장한다.
그렇데면 객체는 어떻게 저장될까? 어떤 클래스의 객체인지에 대한 key value와 함께 메타데이터와 나란히 디스크에 저장되고 데이터가 디스크로부터 읽어들여졌을 때 데이터를 사용해서 객체를 구성한다.
yaml파일은 configuration용도로도 쓰고 log저장할때도 많이 사용한다.
언어별로 객체 구조가 다르므로cross-language data sharing 위해서 제3자인 serialization 언어로 표현함.
옛날에는 xml쓰다가 json으로 넘어갔다. JSON은 자바스크립트의 형식이기 때문에 제3자가 아니다.

Manager&Workers

docker compose up -d docker container ls curl (or web browser) http://localhost:8001 curl (or web browser) http://localhost:8001 docker container exec -it {manager container ID} /bin/sh apk add curl curl http://worker1:80 curl http://worker2:80 docker compose down
YAML
복사
manager의 bash로 들어가서 curl을 수행한다.
위의 주소에서는 localhost:8001을 주소로 수행했는데
아래에서는 worker1 worker2라는 이름을 사용한다.
컨테이너들을 띄우고 논리적인 하나의 네트워크로 묶었기 때문에 자동으로 생성된 네트워크 안에 DNS가 존재해서 도메인 서버가 worker1,2의 ip로 자동 매핑된다. 그래서 ip를 알 필요가 없다.
worker1은 컨테이너 자체가 아니다. 컨테이너는 폴더이름-이미지 이름-인덱스로 명칭이 붙었는데 인덱스가 붙지 않는다. 서비스의 이름으로, 컴퓨터의 메모리를 점유하는 실체가 아닌 클래스와 비슷한 존재이다. worker1으로 수행하면 worker1안에 여러개의 컨테이너가 존재할 수 있고 컨테이너 간의 로드밸런싱을 수행한다.
특정 컨테이너를 더 많이 띄우려면
docker compose up -d --scale worker1=4처럼 실행할 수 있다.
docker-compose를 사용하기 위해 반드시 Dockerfile이 필요한 것은 아닙니다.
Compose 파일에서 서비스 정의 시 이미 존재하는 Docker 이미지를 사용할 수도 있고, 필요하다면 Dockerfile을 사용해 사용자 정의 이미지를 빌드할 수도 있습니다. 아래에 각각의 경우를 설명드리겠습니다.

1. Dockerfile 없이 이미 존재하는 이미지 사용

이미 Docker Hub나 다른 저장소에 있는 이미지를 사용할 때는 Dockerfile이 필요하지 않습니다. 예를 들어, nginxredis 같은 공용 이미지를 직접 가져와서 사용합니다.
docker-compose로 여러개의 컨테이너를 동시에 실행하면 dockerfile여러개로 컨테이너 여러개를 실행하는것과 다른점은 네트워크로 연결되어있다는 점과 scale을 통해 컨테이너 수를 늘리거나 줄이는 기능, depends_on으로 서비스 의존성을 관리하고 동시에 실행하거나 내릴 수 있다는 점이다.
docker build 명령을 사용하여 이미지를 빌드하려면 반드시 Dockerfile이 필요합니다. Dockerfile은 이미지 생성에 필요한 기본 이미지, 명령어, 파일 복사, 환경 설정 등을 정의하므로, docker buildDockerfile 없이 이미지를 빌드할 수 없습니다.
하지만 특정 상황에서는 Dockerfile 없이도 이미지를 생성하거나 컨테이너를 실행할 수 있습니다.

Dockerfile 없이 이미지를 생성하거나 컨테이너 실행하는 방법

1.
Docker Hub의 기존 이미지 사용: Docker Hub와 같은 레지스트리에서 기존 이미지를 바로 다운로드하고 컨테이너를 실행할 수 있습니다. 예를 들어, docker run node:16 명령어로 Node.js 이미지 기반의 컨테이너를 바로 실행할 수 있습니다.
2.
docker-compose.yml에서 기존 이미지 사용: docker-compose.yml 파일에서 image 속성을 사용해 이미 존재하는 이미지를 지정하고, Dockerfile 없이 컨테이너를 구성할 수 있습니다.
이미 빌드된 이미지를 사용하여 배포: docker pull 명령어로 레지스트리에서 이미 빌드된 이미지를 내려받아 사용할 수 있습니다.
networks에서 driver: bridge컨테이너 간 통신을 위한 네트워크 유형을 설정하는 부분으로, Docker에서 기본적으로 제공하는 네트워크 드라이버 중 하나입니다. 이 드라이버는 컨테이너 간 통신을 지원하는 가장 기본적인 네트워크 방식입니다.

Bridge 네트워크란?

Bridge 네트워크는 기본적으로 호스트 시스템 내부에서 컨테이너들을 하나의 가상 네트워크에 연결합니다.
각 컨테이너는 고유한 IP 주소를 가지며, 같은 브리지 네트워크에 속한 컨테이너 간에는 컨테이너 이름을 통해 쉽게 통신할 수 있습니다.
외부에서 컨테이너에 접근하려면 호스트 시스템의 포트를 통해 접근해야 합니다. (예: localhost:5000backend:5000)

Bridge 네트워크의 특징

1.
격리된 네트워크 환경
다른 네트워크에 연결된 컨테이너들은 이 네트워크에 접근할 수 없습니다. 이를 통해 컨테이너 간의 네트워크를 격리할 수 있습니다.
2.
컨테이너 이름으로 접근 가능
동일한 브리지 네트워크에 연결된 컨테이너들은 컨테이너 이름을 도메인 주소처럼 사용하여 통신할 수 있습니다. 예를 들어 backendmongo 컨테이너가 동일한 네트워크에 연결되어 있으면 mongodb://mongo:27017처럼 접근할 수 있습니다.
3.
로컬 개발에 주로 사용
브리지 네트워크는 로컬 개발 환경에서 컨테이너 간 통신을 간단하게 설정하기 위한 기본 네트워크로 주로 사용됩니다.
docker-compose에서 environments를 사용하면 .env 파일이 필요하지 않다. environments 섹션에 직접 환경 변수를 정의할 수 있기 때문입니다. 그러나 .env 파일을 사용하면 여러 서비스에서 공통으로 사용할 환경 변수를 관리하기 용이할 수 있다.
docker공식 이미지 위에서 cmd나 environments등만을 추가하는거라면 굳이 dockerfile을 사용하지 않고 docker-compose에서 사용가능하지만 이미지 빌드해야하면 dockerfile이 필요하다.