REF
https://www.youtube.com/watch?v=EK6iYRCIjYs
$ docker \
run \
--name "db"\
-v "$(pwd)/db_data/var/lib/mysql"\
-e "MYSQL_ROOT_PASSWORD=123456"\
-e "MYSQL_DATABASE=wordpress"\
-e "MYSQL_USER=wordpress_user"\
-e "MYSQL_PASSWORD=123456"\
-network wordpress_net\
mysql:5.7
이라는 도커 컨테이너를 만드는 명령이 있다.
- 도커 컨테이너를 만들때마다 이렇게 복잡한 명령어를 실행해야 한다면 얼마나 귀찮을까.
- 그리고, 이 명령어 하나하나를 기억하고 사용하는게 개인이 가능하더라도 협업하는 동료가 모른다면 얼마나 부담될까.
이렇게 하면 어떨까?
docker-compose.yml이라는 파일을 만들고,
똑같은 일을 하는 코드를 작성한다.
version: "3.7"
services:
db:
image: mysql:5.7
volumes:
- /db_data: /var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress_user
MYSQL_PASSWORD=123456
그리고는 $ docker-compose up 만 실행해주면 컨테이너가 만들어진다면?
위의 역할을 Docker Compose가 가능케 한다!
wordpress를 열어보니 Docker이미지를 이용해서 컨테이너를 이용해서 실행하고 싶다.
wordpress Docker 이미지는 MySQL 컨테이너가 하나 더 필요하다.
wordpress 컨테이너와 MYSQL 컨테이너를 만들고 두개를 연결시키면
웹 브라우저에서 Wordpress 컨테이너를 작동시키면 WordPress 컨테이너가 MySQL 컨테이너에서 작업 후
그 결과를 가져온 다음에 그걸 웹 브라우저에 다시 보내주게 된다.
실습해보자
1. network를 만들어준다.
docker network create wordpress_net
2. 'db'라는 이름의 , MySQL 이미지를 기반으로 컨테이너를 만드는 run 명령을 실행시킨다.
docker \
run \
--name "db" \
-v "$(pwd)/db_data:/var/lib/mysql" \
-e "MYSQL_ROOT_PASSWORD=123456" \
-e "MYSQL_DATABASE=wordpress" \
-e "MYSQL_USER=wordpress_user" \
-e "MYSQL_PASSWORD=123456" \
--network wordpress_net \
mysql:5.7
-> host에 db_data라는 폴더가 생긴다. 이 폴더에는 MySQL의 데이터가 저장되는 파일이 생성된다.
이것 덕분에 DB를 껐다가 다시 켤때 실제로 데이터가 저장되는 db_data는 온전히 저장되어있기에
컨테이너를 껐다가 켜도 data가 사라지지 않는다.
3. WordPress를 실행하는 컨테이너를 run 실행시킨다.
docker \
run \
--name app \
-v "$(pwd)/app_data:/var/www/html" \
-e "WORDPRESS_DB_HOST=db" \
-e "WORDPRESS_DB_USER=wordpress_user" \
-e "WORDPRESS_DB_NAME=wordpress" \
-e "WORDPRESS_DB_PASSWORD=123456" \
-e "WORDPRESS_DEBUG=1" \
-p 8080:80 \
--network wordpress_net \
wordpress:latest
MySQL과 WordPress 두 컨테이너를 생성시켜주었고, 이 두 컨테이너는 wordpress_net이라고 하는 네트워크에 연결되어있는 상태이다.
wordpress도 역시나 호스트에 파일을 카피하고 있다.
4. WordPress에 접속한다. localhost:8080
=> WordPress를 설치하는 화면이 나온다.
근데 너무나 복잡하다
언제 저 코드 하나하나를 치고있나
Docker compose up으로 한번에 해결하자
예제를 진행하면서 생긴 폴더, 컨테이너를 정리 후에 실행해주어야 한다.
1. 기존에 생성했던 컨테이너를 지워준다.
docker rm --force app
docker rm --force db
docker network rm wordpress_net
2. 생성되었던 폴더 app_data, db_data 도 지워준다.
3. docker-compose.yml 이라는 약속된 이름의 파일을 만들어준다.
docker-compose.yml 파일은 한번 저장해준뒤에 사용해야 적용된다
else -> "Top-level object must be a mapping" 에러를 만나게 된다.
docker compose up
을 입력해주면 실행이 시작되된다.
에러:
no matching manifest for linux/arm64/v8 in the manifest list entries
원인 : 도커 허브의 MySQL 이미지에서 당겨오는 과정중에 오류가 발생했다.(M1 mac)
해결1: 도커 명령어 옵션으로 '--platform linux/amd64' 를 붙여 이미지를 당겨오는 플랫폼이 arm64환경이 아니라
amd64의 linux환경이라고 명시함으로써 에러를 피해간다.
docker pull --platform linux/amd64 mysql:8
즉, 위와같은 코드로 이미지를 당겨와서, 다시 docker compose up을 진행한다.
해결2: mysql 버전을 latest, 즉
services:
db:
image: mysql:latest
로 바꾸어준다.
이후 docker compose up을 입력하고 localhost:8080을 입력하면
Wordpress 설치환경이 실행된다.
종료하기
docker compose down
하면 docker가 닫히게 된다.
매커니즘
Shell vs docker-compose
1. MySQL 서버 컨테이너 만들기
MySQL Server 컨테이너를 만들면 /var/lib/mysql 이라는 폴더에 데이터가 저장이 된다.
MySQL 서버는 3306번 포트에 listening 되게 된다.
MySQL 서버를 만들기 위해서는
2Shell에서는 docker run 명령어를 사용하게 된다. 그리고 mysql:latest라고 하면 컨테이너가 만들어진다.
같은 매커니즘을 docker-compose.yml로 구현하기 위해서는 "이 파일의 version"을 적어주어야한다.
services라고 하는 지시어를 선언하면 이 지시어 안에는 우리가 원하는 컨테이너를 구현할 수 있다.
그리고, Shell에서는 "--name 'db'\" 로 선언하지만 docker-compose.yml에서는 services: 아래에 db: 라고 써주면 된다.
2. 데이터 유실 방지하기
여기서 문제가 있다.
컨테이너 안에 파일이 저장이 되므로, 컨테이너를 새로만들거나하면 데이터가 유실된다.
=> 컨테이너의 바깥인 host 안에 데이터를 저장한다면 컨테이너가 수정되거나 사라져도 데이터가 유지될 수 있다
Shell에서는
-v "$(pwd)/db_data:/var/lib/mysql" \
는 [현재 디렉토리아래에 있는 db_data]와 [컨테이너의 /var/lib/mysql/] 을 연결한다는 뜻이다.
docker-compose.yml 에서는
volumes:
-./db_data:/var/lib/mysql
로 선언해주면 된다.
3. 환경 변수 설정하기
MySQL 서버의 UserId, password 등
컨테이너들을 만들어 놓은 사람이 제시하는 환경변수를 세팅하면
컨테이너가 만들어질 때 여러 정보들이 세팅된다.
Shell: "-e" 옵션
docker-compose.yml: "environment" 옵션
4. WordPress 어플리케이션을 컨테이너로 만들기
wordpress 컨테이너에는 apache 웹서버와 PHP가 설치되어있고, /var/www/html/이라는 디렉토리에 PHP로 만들어진 소스코드가 보관되게 된다.
웹서버가 80번 포트에 listening 되게 된다.
한편, docker-compose.yml 에서 사건의 선행/후행 을 따져주기 원한다면 'depends_on' 옵션을 주면 된다.
depends_on:
- db
이라고 하면 db가 생성된 후에 해당 컨테이너가 만들어지게 된다.
그리고, wordpress의 데이터 폴더인 /var/www/html/ 에 접근하고 싶다면 app_data을 만들어주자.
5. 보안 조건 설정해주기
컨테이너중에 외부에서 접근이 가능한 컨테이너와 보안상의 이유로 접근이 불가능한 컨테이너를 나누어주어야한다.
하지만 database는 app Container만 db 컨테이너에 접근 가능하게 하는것이 훨씬 안전하다.
app Container의 80번 포트와 host의 8080포트를 연결시켜서
8080 포트로 접속이 되면 80번 포트에서 listening 하고있는 Web Server가 접속을 받을 수 있게 해주고 싶다.
우리가 만든 Wordpress App 이 db에 접속하기 위해서는 db에 대한 정보가 필요하다.
-> 환경변수를 넣어주자!
wordPress 입장에서 db를 연결하려 할때
IP주소나, 복잡한 식이 아니라
컨테이너의 이름인 "db"를 적었을 때 접속이 가능하다면 얼마나 편할까?
-> 네트워크를 만들어주면 된다!!!!!
[네트워크 만들어주기]
Shell: "docker network create wordpress_net"
[db 컨테이너를 네트워크에 연결시키기]
Shell: --networok wordpress_net\
docker-compose에서는 네트워크를 만들고 연결해줄 필요가 없다.
컨테이너가 만들어 질 때 네트워크가 자동으로 만들어지고,
생성된 네트워크에 자동으로 연결된다.
6. 매커니즘 이해하기
①host의 http://localhost:8080 포트로 들어오면 80번 포트에 연결되어있는 app Container로 연결이 된다
②80번 포트에서 listening 하고 있는 웹서버에 접속이 들어간다.
③웹서버는 PHP에게 그 요청을 넘기고 PHP는 /var/www/html/에 위치하고 있는
PHP 애플리케이션을 읽어서 거기에 있는대로 동작하게 된다.
④예를들어 mysql_connect('db', 'wordpress_user', '123456'); 정보를 입력하면,
⑤db는 같은 네트워크에 접속되어있는 db라는 이름의 컨테이너를 의미한다. (3306)
3306번을 listening 하고있는 mySQL 서버가 그걸 받고,
⑥MySQL 서버는 /var/lib/mysql 이라는 디렉토리에 연결되어 있는 db에서 데이터를 꺼내서
⑦그 결과를 PHP에 돌려주고,
⑧ PHP는 웹서버에게 응답하고, 웹서버는 다시 웹 브라우저에게 결과를 알려준다.
=> 웹브라우저에는 wordpress가 실행되게 된다.
Shell | Docker-compose.yml |
docker \ run ... mysql:latest |
version: '3.7' servicese: image: mysql:latest |
--name 'db'\ | db: |
-v "$(pwd)/db_data:/var/lib/mysql"\ | volumes: -./db_data:/var/lib/mysql |
-e | environment: |
-- network wordpress_net\ | 필요없음 |
- 마무리
Docker compose는 매우 편리하다.
compose를 이용해 복잡한 컨테이너 간 관계를 명확하게 문서화 할 수 있고,
매우 손쉽게 컨테이너를 다룰 수 있다.
위에 제시된 옵션외에도 많은 옵션이 사용될 수 있다.
아래 documentation을 참조바란다.
'IT 지식' 카테고리의 다른 글
"Map 과 HashMap의 차이가 뭐에요?" (내 얘기) (0) | 2022.12.23 |
---|---|
[조건문] switch-case vs if-else (0) | 2022.12.05 |
[Docker] docker-compose 설치하기 (0) | 2022.12.01 |
[Docker] Docker로 MySQL설치하고 접속하기 (0) | 2022.12.01 |
MVC 웹 프레임워크란? (1) | 2022.12.01 |