> For the complete documentation index, see [llms.txt](https://container.youngwjung.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://container.youngwjung.com/docker-compose.md).

# Docker Compose

### 멀티 컨테이너 환경

1. 데모 애플리케이션 소스코드 다운로드

   ```
   git clone https://github.com/youngwjung/to-do.git && cd to-do
   ```
2. 애플리케이션 소스 코드 및 README 리뷰&#x20;
3. Dockerfile 생성&#x20;

   ```
   cat <<EOF | tee frontend/Dockerfile
   FROM nginx:alpine
   COPY . /usr/share/nginx/html
   EOF
   ```
4. 프론트엔드 컨테이너 이미지 생성

   ```
   docker image build -t frontend frontend/
   ```
5. 프론트엔드 컨테이너 생성

   ```
   docker container run --name frontend -d -p 8080:80 frontend
   ```
6. 웹브라우저에서 컨테이너로 접근되는지 확인 - 아래 명령어로 주소 확인 가능

   ```
   echo "$(curl -s ifconfig.io):8080"
   ```
7. Dockerfile 변경&#x20;

   ```
   cat <<'EOF' | tee frontend/Dockerfile
   FROM nginx:alpine
   COPY . /usr/share/nginx/html
   ARG API_ENDPOINT
   RUN sed -i 's/localhost:9000/'"$API_ENDPOINT"'/g' /usr/share/nginx/html/js/main.js
   EOF
   ```
8. 프론트엔드 컨테이너 이미지 재생성

   ```
   docker image build --no-cache -t frontend \
   --build-arg API_ENDPOINT=$(curl -s ifconfig.io):9000 \
   frontend/
   ```
9. 프론트엔드 컨테이너 재생성

   ```
   {
       docker container rm frontend --force
       docker container run --name frontend -d -p 8080:80 frontend
   }
   ```
10. 웹 브라우저에서 로딩된 페이지 리프레시&#x20;
11. Dockerfile 생성&#x20;

    ```
    cat <<EOF | tee api/Dockerfile
    FROM golang:1.20-alpine as builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY *.go ./
    RUN go build -o /api

    FROM alpine
    RUN mkdir /app
    WORKDIR /app
    COPY --from=builder /api /app/api
    EXPOSE 9000
    CMD ["/app/api"]
    EOF
    ```
12. API 컨테이너 이미지 생성

    ```
    docker image build -t api api/
    ```
13. API 컨테이너 생성

    ```
    docker container run --name api -d -p 9000:9000 api
    ```
14. API 컨테이너 상태 확인

    ```
    docker container ls -a
    ```
15. API 컨테이너 로그 확인

    ```
    docker logs api
    ```
16. MySQL 컨테이너 생성

    ```
    docker container run --name mysql -d -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=asdf1234 mysql:5.7
    ```
17. 데이터베이스 스키마 생성

    ```
    mysql -h 127.0.0.1 -u root -pasdf1234 < database/schema.sql
    ```
18. API 컨테이너 재생성

    ```
    {
        docker container rm api --force
        docker container run --name api -d -p 9000:9000 \
        -e DATABASE_HOST=$(docker container inspect mysql --format '{{.NetworkSettings.IPAddress}}') \
        -e DATABASE_PASSWORD=asdf1234 \
        api
    }
    ```
19. API 컨테이너 로그 확인

    ```
    docker logs api
    ```
20. Redis 컨테이너 생성

    ```
    docker container run --name redis -d redis
    ```
21. API 컨테이너 재생성

    ```
    {
        docker container rm api --force
        docker container run --name api -d -p 9000:9000 \
        -e DATABASE_HOST=$(docker container inspect mysql --format '{{.NetworkSettings.IPAddress}}') \
        -e DATABASE_PASSWORD=asdf1234 \
        -e REDIS_HOST=$(docker container inspect redis --format '{{.NetworkSettings.IPAddress}}') \
        api
    }
    ```
22. 실행중인 컨테이너 목록 확인

    ```
    docker container ls
    ```
23. 보안그룹에 인바운드 규칙 추가

    ```
    aws ec2 authorize-security-group-ingress \
    --group-id $(aws ec2 describe-security-groups \
    --filters Name=group-name,Values=$(curl -s http://169.254.169.254/latest/meta-data/security-groups) \
    --query "SecurityGroups[0].GroupId" --output text) \
    --protocol tcp \
    --port 9000 \
    --cidr 0.0.0.0/0 \
    --output text
    ```
24. 웹 브라우저에서 로딩된 페이지 리프레시&#x20;
25. 리소스 정리

    ```
    {
        docker container rm $(docker container ls -aq) --force
        docker image prune --all --force
        docker volume prune --force
        cd ~/environment
    }
    ```

### Docker Compose

1. Docker Compose 설치

   ```
   {
       sudo mkdir -p /usr/local/lib/docker/cli-plugins
       sudo curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
       sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
   }
   ```
2. Docker Compose 설치 확인&#x20;

   ```
   docker compose version
   ```
3. 워드프레스를 구성할 Compose 파일 생성&#x20;

   ```
   mkdir wordpress && cd wordpress && \
   cat <<EOF | tee docker-compose.yml
   services:
     wordpress:
       image: wordpress
   EOF
   ```
4. Compose 파일에 명시된 구성대로 컨테이너 환경 생성

   ```
   docker compose up -d
   ```
5. 실행중인 Compose 프로젝트 목록 확인

   ```
   docker compose ls
   ```
6. Compose 파일 수정&#x20;

   ```
   cat <<EOF | tee docker-compose.yml
   name: blog
   services:
     wordpress:
       image: wordpress
   EOF
   ```
7. 수정 사항 반영

   ```
   docker compose up -d
   ```
8. 실행중인 Compose 프로젝트 목록 확인

   ```
   docker compose ls
   ```
9. 수정하기전 버전의 Compose 파일로 생성된 리소스를 수동으로 삭제

   ```
   {
       docker container rm wordpress-wordpress-1 --force
       docker network rm wordpress_default
   }
   ```
10. Compose를 통해서 실행중인 컨테이너 목록 확인

    ```
    docker compose ps
    ```
11. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        image: wordpress
        container_name: wordpress
    EOF
    ```
12. 수정 사항 반영

    ```
    docker compose up -d
    ```
13. Compose를 통해서 실행중인 컨테이너 목록 확인

    ```
    docker compose ps
    ```
14. 실행중인 모든 컨테이너 목록 확인&#x20;

    ```
    docker container ls
    ```
15. NGINX 컨테이너 생성

    ```
    docker run --name nginx -d nginx
    ```
16. 실행중인 모든 컨테이너 목록 확인&#x20;

    ```
    docker container ls
    ```
17. Compose를 통해서 실행중인 컨테이너 목록 확인

    ```
    docker compose ps
    ```
18. 새로운 터미널을 열고 Compose를 통해서 실행중인 컨테이너 목록 확인

    ```
    docker compose ps
    ```
19. 실행중인 Compose 프로젝트 목록 확인

    ```
    docker compose ls
    ```
20. 생성된 모든 컨테이너에 부여된 Label 확인&#x20;

    ```
    docker container inspect \
    $(docker container ps -aq) --format '{{.Name}} - {{json .Config.Labels}}'
    ```
21. 기존 터미널로 이동해서 NGINX 삭제&#x20;

    ```
    docker container rm nginx --force
    ```
22. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        image: wordpress
        container_name: wordpress
        ports:
        - 8080:80
    EOF
    ```
23. 수정 사항 반영

    ```
    docker compose up -d
    ```
24. 웹브라우저에서 포트포워딩한 포트를 통해서 컨테이너로 접근되는지 확인 - 아래 명령어로 주소 확인 가능

    ```
    echo "$(curl -s ifconfig.io):8080"
    ```
25. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        image: wordpress
        container_name: wordpress
        ports:
        - 8080:80
        environment:
        - WORDPRESS_DB_HOST=mysql
        - WORDPRESS_DB_USER=wordpress
        - WORDPRESS_DB_PASSWORD=wordpress
        - WORDPRESS_DB_NAME=wordpress
        depends_on:
        - mysql
      mysql:
        image: mysql
        volumes:
        - mysql-data:/var/lib/mysql
        environment:
        - MYSQL_ROOT_PASSWORD=asdf1234
        - MYSQL_USER=wordpress
        - MYSQL_PASSWORD=wordpress
        - MYSQL_DATABASE=wordpress
    volumes:
      mysql-data:
    EOF
    ```
26. 수정 사항 반영

    ```
    docker compose up -d
    ```
27. 웹브라우저에서 워드프레스 사이트 재접속 - 아래 명령어로 주소 확인 가능

    ```
    echo "$(curl -s ifconfig.io):8080"
    ```
28. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        image: wordpress
        container_name: wordpress
        volumes:
        - plugins:/var/www/html/wp-content/plugins
        ports:
        - 8080:80
        environment:
        - WORDPRESS_DB_HOST=mysql
        - WORDPRESS_DB_USER=wordpress
        - WORDPRESS_DB_PASSWORD=wordpress
        - WORDPRESS_DB_NAME=wordpress
        depends_on:
        - mysql
        - wordpress-init
      mysql:
        image: mysql
        volumes:
        - mysql-data:/var/lib/mysql
        environment:
        - MYSQL_ROOT_PASSWORD=asdf1234
        - MYSQL_USER=wordpress
        - MYSQL_PASSWORD=wordpress
        - MYSQL_DATABASE=wordpress
      wordpress-init:
        image: alpine
        volumes:
        - plugins:/plugins
        command:
        - "sh"
        - "-c"
        - "wget -O https://downloads.wordpress.org/plugin/classic-editor.1.6.3.zip && unzip -o classic-editor.1.6.3.zip -d /plugins"
    volumes:
      mysql-data:
      plugins:
    EOF
    ```
29. 수정 사항 반영

    ```
    docker compose up -d
    ```
30. 플러그인이 추가 되었는지 확인&#x20;
31. wp-cli를 통해서 워드프레스 테마 설치 시도&#x20;

    ```
    docker compose exec wordpress wp theme install blocksy --activate --allow-root
    ```
32. Dockerfile 생성&#x20;

    ```
    cat <<EOF | tee Dockerfile
    FROM wordpress
    RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
        chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp
    EOF
    ```
33. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        build: .
        container_name: wordpress
        volumes:
        - plugins:/var/www/html/wp-content/plugins
        ports:
        - 8080:80
        environment:
        - WORDPRESS_DB_HOST=mysql
        - WORDPRESS_DB_USER=wordpress
        - WORDPRESS_DB_PASSWORD=wordpress
        - WORDPRESS_DB_NAME=wordpress
        depends_on:
        - mysql
        - wordpress-init
      mysql:
        image: mysql
        volumes:
        - mysql-data:/var/lib/mysql
        environment:
        - MYSQL_ROOT_PASSWORD=asdf1234
        - MYSQL_USER=wordpress
        - MYSQL_PASSWORD=wordpress
        - MYSQL_DATABASE=wordpress
      wordpress-init:
        image: alpine
        volumes:
        - plugins:/plugins
        command:
        - "sh"
        - "-c"
        - "wget -O https://downloads.wordpress.org/plugin/classic-editor.1.6.3.zip && unzip -o classic-editor.1.6.3.zip -d /plugins"
    volumes:
      mysql-data:
      plugins:
    EOF
    ```
34. 수정 사항 반영

    ```
    docker compose up -d
    ```
35. 웹 브라우저에서 위드프레스 메인 페이지로 이동해서 테마 확인&#x20;
36. wp-cli를 통해서 워드프레스 테마 설치&#x20;

    ```
    docker compose exec wordpress wp theme install blocksy --activate --allow-root
    ```
37. 웹 브라우저에서 위드프레스 메인 페이지로 이동해서 테마 확인&#x20;
38. wordpress 컨테이너에서 실행중인 프로세스 확인

    ```
    docker compose top
    ```
39. wordpress 컨테이너에서 에러가 발생했다고 가정하고 실행중인 프로세스 종료&#x20;

    ```
    docker compose exec wordpress pkill apache2
    ```
40. 워드프레스 사이트에 접속 되는지 확인&#x20;
41. Compose 프로젝트 상태 확인

    ```
    docker compose ls
    ```
42. wordpress 컨테이너가 실행중인지 확인&#x20;

    ```
    docker compose ps -a
    ```
43. Compose 파일 수정&#x20;

    ```
    cat <<EOF | tee docker-compose.yml
    name: blog
    services:
      wordpress:
        build: .
        container_name: wordpress
        restart: always
        volumes:
        - plugins:/var/www/html/wp-content/plugins
        ports:
        - 8080:80
        environment:
        - WORDPRESS_DB_HOST=mysql
        - WORDPRESS_DB_USER=wordpress
        - WORDPRESS_DB_PASSWORD=wordpress
        - WORDPRESS_DB_NAME=wordpress
        depends_on:
        - wordpress-init
      mysql:
        image: mysql
        volumes:
        - mysql-data:/var/lib/mysql
        environment:
        - MYSQL_ROOT_PASSWORD=asdf1234
        - MYSQL_USER=wordpress
        - MYSQL_PASSWORD=wordpress
        - MYSQL_DATABASE=wordpress
      wordpress-init:
        image: alpine
        volumes:
        - plugins:/plugins
        command:
        - "sh"
        - "-c"
        - "wget -O https://downloads.wordpress.org/plugin/classic-editor.1.6.3.zip && unzip -o classic-editor.1.6.3.zip -d /plugins"
    volumes:
      mysql-data:
      plugins:
    EOF
    ```
44. Compose 프로젝트 재실행&#x20;

    ```
    docker compose up -d
    ```
45. 워드프레스 사이트에 접속 되는지 확인
46. &#x20;wordpress 컨테이너에서 에러가 발생했다고 가정하고 실행중인 프로세스 종료&#x20;

    ```
    docker compose exec wordpress pkill apache2
    ```
47. 워드프레스 사이트에 접속 되는지 확인
48. wordpress 컨테이너가 실행중인지 확인&#x20;

    ```
    docker compose ps
    ```
49. wordpress 컨테이너가 삭제되면 다시 생성 될까요?

    ```
    docker container rm wordpress --force
    ```
50. wordpress 컨테이너가 실행중인지 확인&#x20;

    ```
    docker compose ps -a
    ```
51. Compose 프로젝트 삭제

    ```
    docker compose down
    ```
52. Compose에 명시했던 Volume들이 남아 있는지 확인

    ```
    docker volume ls
    ```
53. Compose 프로젝트 생성

    ```
    docker compose up -d
    ```
54. 웹브라우저에서 워드프레스 사이트 재접속 - 아래 명령어로 주소 확인 가능

    ```
    echo "$(curl -s ifconfig.io):8080"
    ```
55. Compose 프로젝트 삭제

    ```
    docker compose down --volumes
    ```
56. [#undefined](#undefined "mention")에서 개별로 생성했던 애플리케이션들을 Docker Compose를 통해서 구성
57. 리소스 정리

    ```
    {
        docker compose down --volumes
        docker container rm $(docker container ls -aq) --force
        docker image prune --all --force
        docker volume prune --force
        docker system prune --all --force
        cd ~/environment
    }
    ```
