![[Docker] 5. 도커 컴포즈](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BDocker%255D%25205.%2520%25EB%258F%2584%25EC%25BB%25A4%2520%25EC%25BB%25B4%25ED%258F%25AC%25EC%25A6%2588%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3Djay0628&w=2048&q=75)
컴포즈로는 배포 못 함!
컴포즈는 로컬에서 연습할 때 사용하는 것
호스트 컴퓨터와 컨테이너는 같은 계층 layer에 뜬다.
도커 엔진 내에 도커 api 서버가 있음
호스트에서 명령어 → 도커 엔진으로 감
실제로는 명령어가 아니라 프로세스간의 통신을 해야하는데
같은 애플리케이션 하나의 클래스에서는 힙을 공유해서 메서드
다른 애플리케이션에서는 프로세스간 통신 방법
- 서버를 두고 서버에 메세지 던져서 주고 받고
- OS로 주고 받고
호스트 컴퓨터 - 가상화 →가상 네트워크 (진짜 네트워크 세상(공유기, www(LAN, WAN))은 아님)
도커 컴포즈 = pc가 다르면 결합이 안됨
도커 엔진 api는 사설 DNS 서버를 가짐→ N1과 N2의 위치를 가짐
다른 네트워크 이름으로 찾을 수 있음
IP대역대가 같아짐
CIDR 가능

도커 컴포즈 기본
docker-compose.yml 이름 변형 불가!
버전마다 문법이 조금씩 다르기 때문에 버전이 중요!
yml은 key값이 붙고 : 뒤에 한 칸을 무조건 띄운다. 내부에 쓸 때는 두 칸 띄운다. -는 배열
도커 컴포즈는 하나의 컨테이너를 마이크로한 서비스로 본다.
따라서 services 안에는 컨테이너가 들어와야 한다.
- my_server : 이미지 이름 = 변수
- build : 이미지 이름 받아서 설정 여기서 쓰고 해서 띄우지 말고 도커 파일을 찾아서 띄우기! 도커 파일로 세팅하기!!!!!!
- ./server 내부의 Dockerfile로 빌드하겠다
docker-compose up -d
이미지 굽고 컨테이너 실행하고 등등 다 되어있는거임
근데 apt update 등 모든건 dockerfile에서 하기






컴포즈 죽이기…
docker-compose down

기본버전
버전(최신버전으로) 서비스들(= 컨테이너들) 이미지 직접 굽지 말고 Dockerfile쓰기 포트 재시작
두 개의 서비스 연결하기

- version :
- services:
- build:
- context:
- ports:
- restart:
- networks:
- drivers:
- depends_on:
- environment:

db가 먼저 떠야 spring 서버 실행시 db와 연결되면서 터지지 않는다.
depends_on:
서비스를 이름으로 찾는다는거는
서비스 이름으로 사설 네트워크로 뜬 가상 컨테이너를 찾아서 켜졌는지, entrypoint가 실행됐는지, 프로세스가 떴는지 등 전부 체크해준다는 것!
이거 안하면 두 개 동시에 떠서 터진다.
environment : 컨테이너가 떠서 실행이 되는 순간
디스크에 기록X 컨테이너 뜨기 직전에 잠깐 뜸
근데 dockerfile의 env에 적는건 다름 → 이미지에 환경변수가 귀속된다. 다르다.
⇒ 타이밍 문제로 나중에 멘탈깨질수 잇으니 주의…
이미지가 실행됐을 때 외부에 뜨는게 environment
이미지에 기록되어있는게 Dockerfile의 env

Dockerfile에 맞춰서 docker-compose.yml을 쓰기
hostname에 서비스명을 적으면 찾아줌..
서비스명으로 DNS을 찾아서 DNS의 IP 주소 갱신 → 서비스 디스커버리 (유레카 디스커버리?
도커파일을 가지고 from myqsl → pull
env 설정
이미지가 실행돼서 내부에 환경변수가깔린것
run 해서 apt update나 시간ㅅㄹ정 가능 → 이때 env에 적은 환경변수 당연히 땡겨짐
yml에 쓴 내용은 안땡겨짐
이때는 env만 땡겨서 쓰고
→ 굽기위해서 run을하는것과 최종적으로 run을하는 것은 다름
완전히 구워지고 나서 엔트리포인트로 실행될때는 진짜 실행되는거 이때는 yml파일의 environment의 환경변수를 땡길 수 있음
⇒ 중요하니까 기억하기!!!!!!!!!!!!!
from과 copy 사이에 docker run이 된거임
이미지 굽기 위한 프로비저닝 → entrypoint.sh
계속 RUN써서 dockerfile에서 쓰는건 별로
스크립트는 따로 만들어서 작성하는게 낫다.
build는 준비
build를 하면 실행을 해야함
도커 파일도 빌드를 하면 이미지를 굽는게 목적이므로 직접 실행을 해줘야 됨
도커 컴포즈는 이미지들을 들고와서 연결해서 실행시켜줌
context에 도커파일을 뒀으니
빌드부터 시작됨
서비스 = pods (찐 이름은 이거) = 컨테이너들을 묶는 단위인 "파드(Pod)
엔트리포인트를 기반으로 run이 실행됨
내가 안만들면 디폴트 네트워크가 생겨짐 폴더명으로 생겨짐 → 사설 네트워크가 하나가 뜸 (ex) ex07_network 이런식으로
지금 박스 3개 만들어진거

gateway가 만들어지는데 bridge 적으면 host 시스템에서 컨테이너로 바로 접근 못하는
공유기 = gateway ip
같은 클러스터 내에 존재하면 서비스 디스커버리에 의해 이름을 ip 주소로 변환해줌

뭐부터 실행되는지 적어보면서 추적해보기
이 컨테이너의 ip를 찾아보는 명령어 등등 명령어 gpt한테 물어보기


Mysql이 실행중이면 종료해야 컨테이너가 실행된다!!


docker inspect 컨테이너ID


전체 코드
docker-compose.yml
version: "3.8"
services:
my_db:
build:
context: ./db
ports:
- "3306:3306"
restart: always
networks:
- backend_network
volumes:
- my_db_data:/var/lib/mysql
my_server:
build:
context: ./server
ports:
- "8080:8080"
restart: always
depends_on:
- my_db
environment:
- RDS_HOSTNAME=my_db
- RDS_PORT=3306
- RDS_USERNAME=ssar
- RDS_PASSWORD=ssar1234
- RDS_DB_NAME=blogdb
networks:
- backend_network
networks:
backend_network:
driver: bridge
frontend_network:
driver: bridge
db/Dockerfile
FROM mysql
COPY init.sql /docker-entrypoint-initdb.d/init.sql
ENV MYSQL_USER=ssar
ENV MYSQL_PASSWORD=ssar1234
ENV MYSQL_ROOT_PASSWORD=root1234
ENV MYSQL_DATABASE=blogdb
CMD ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
EXPOSE 3306
db/init.sql
use blogdb;
CREATE TABLE IF NOT EXISTS user_tb (
id integer auto_increment,
created_at timestamp,
email varchar(20) not null,
password varchar(60) not null,
username varchar(20) not null unique,
profile varchar(100),
primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS board_tb (
id integer auto_increment,
content varchar(10000),
created_at timestamp,
title varchar(100) not null,
user_id integer,
primary key (id),
constraint fk_board_user_id foreign key (user_id) references user_tb (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS reply_tb (
id integer auto_increment,
comment varchar(100) not null,
created_at timestamp,
board_id integer,
user_id integer,
primary key (id),
constraint fk_reply_board_id foreign key (board_id) references board_tb (id),
constraint fk_reply_user_id foreign key (user_id) references user_tb (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
FLUSH PRIVILEGES;
server/Dockerfile
FROM openjdk:11-jdk-slim
RUN apt-get update
RUN apt-get install -y git
WORKDIR /app
COPY ./entrypoint.sh ./entrypoint.sh
RUN ["chmod", "+x", "entrypoint.sh"]
EXPOSE 8080
ENTRYPOINT ["/bin/bash", "./entrypoint.sh"]
server/entrypoint.sh
git clone https://github.com/busanuv/blog-last.git cd blog-last chmod +x gradlew ./gradlew build chmod +x build/libs/*.jar java -jar -Dspring.profiles.active=docker build/libs/*.jar
docker-compose up을 하면 build가 1번
실행시에만 depends-on이 발동 build할때는 X


dockerfile의 env에 환경변수로 서비스명을 적어두면 서비스가 아직 안떴기 때문에 서비스에 뜰 때 dns에 등록되므로 my_db글자가 환경변수에 찍힘 ip주소가 아니라. 그래서 멘탈이 깨져용
이미지 구워지는 순간에는 DNS에 my_db 없음 이미지 둘 다 구워지고 나서 컨테이너 뜨니까
뭐가 interceptor..?낚아채서 my_db
순서
yml에 rds_hostname 땡길때 my_db라고 적혀있으니까 도커가 낚아채서 실제 ip를 찾음 그리고 걔가 등록된다.
브릿지는 포트포워딩으로만 들어가고 host로 바로 못들어감 근데 몰라도 되고 걍 다 쓰면댐

Share article