Docker

freshness·2024년 5월 8일
post-thumbnail

[출처] 유데미 - Docker & Kubernetes : 실전가이드

초보를 위한 도커 안내서 - 도커란 무엇인가?

Docker 란?

  • 컨테이너를 생성하고 관리하기 위한 도구

Docker의 장점

  • Docker만 설치하면 로컬에 별도의 프로그램 설치가 필요하지 않다.
    • Docker 이미지에 파이썬이 포함되어 있는 경우 로컬 환경에 파이썬을 설치하지 않고 파이썬을 사용할 수 있다.
  • 개발 환경에 포함된 모든 설정을 프로덕트 환경에 동일하게 적용 할 수 있다.
  • 개발 환경을 공유하고 설치하기 쉬워진다.

Docker(Container)와 VM(Hypervisor)의 차이점

출처

Docker 와 VM의 차이점

  • VM - Hypervisor를 이용해 OS와 자원을 할당한 상태에서 VM 을 생성
    • Host의 자원을 이용한 가상 OS를 통째로 실행
  • Docker - Host OS의 커널을 공유 받아 OS 이미지 없이 App 실행에 필요한 부분만을 묶어 실행
  • Docker의 경우 Host OS의 커널을 공유 받기 때문에 OS가 불안정할 경우 Container에 영향이 간다.
  • VM은 OS 이미지를 포함해 실행되기 때문에 Docker와 다르게 다양한 OS를 설정해 사용할 수 있다.
  • 최근 대부분의 기술들이 리눅스 기반으로 진행되기 때문에 특수한 환경이 아닌 이상 VM보다는 Docker가 더 유리할 수 있을 것 같다고 생각된다.

이미지 & 컨테이너

  • 이미지
    • 컨테이너의 설계도(=설치 CD의 개념과 유사)
    • 코드와 코드를 실행하는데 필요한 도구를 포함
    • 읽기 전용
  • 컨테이너
    • APP, 웹 사이트, 환경(소프트웨어 유닛) 등을 포함하는 작은 패키지

Docker 설치

  1. Docker 설치 가이드는 공식 사이트의 Docker Engine 설치 참조(링크)
  2. 설치된 Docker는 root 권한만 사용 가능하며, 이외 사용자들은 docker 라는 그룹에 소속되어 있어야 docker 명령어를 사용할 수 있다.
    1. grep docker /etc/group
    2. sudo usermod -aG docker vagrant
      1. -G : 추가 그룹
  3. 사용자 별로 이미지, 네트워크, 볼륨을 관리하며 최초 shell 접속 아이디를 기준으로 인식한다.(su로 유저 전환해도 보이지 않음)

Dockerfile

  • FROM : Dockerhub에서 다운로드할 이미지 이름과 버전(=태그)
  • WORKDIR : 컨테이너가 생성될 떄 설정되는 작업 폴더
  • COPY : 호스트 OS의 파일을 컨테이너의 작업 폴더로 복사
    • Host = Docker가 실행되고 있는 OS(내 컴퓨터)
  • RUN : 이미지가 빌드되는 순간 실행되는 명령어
  • EXPOSE : 오픈할 포트를 명시 (실제 오픈되지는 않음)
    • docker run 시 -p 옵션을 주면 Host의 랜덤 포트와 컨테이너의 EXPOSE 포트가 매핑되어 동작한다.
  • CMD : 컨테이너가 실행(run)할 때 최초로 동작하는 명령어

Attached(연결) & Detached(분리) & Interactive(상호작용) 모드

  • Attached
    • docker run을 통해 컨테이너를 생성할 때 attached가 기본값
    • 컨테이너의 출력 결과를 수신할 수 있는 모드(입력은 불가)
  • Detached
    • 컨테이너가 백그라운드에서 돌아가고 있는 중이며 터미널을 통해 응답을 받을 수 없는 상태
    • docker start로 실행하는 경우 detached가 기본값
  • Interactive
    • 컨테이너에 입출력 상태를 열어 놓는 모드
    • docker run 시 -i(=interactive) 옵션을 통해 활성화가 가능하며 -t(=tty) 옵션을 같이 줘서 터미널로 컨테이너와 상호작용 할 수 있으며 -it 로 합쳐서 옵션을 입력한다.
    • docker start 시 -a(=attach), -i(=interactive) 옵션을 통해 터미널로 컨테이너와 상호작용 할 수 있다.

이미지의 고유식별자

  • name : 이미지의 고유 식별자 (=프로그램 이름)

  • tag : name 안에서 사용되는 고유 식별자 (=버전)

  • 이미지 태그 부여 방법

    • docker build -t : . ← 현재 디렉토리
  • Docker Image의 tag 변경 방법

    # 변경할 태그는 생략할 경우 자동으로 lastest로 설정
    docker tag <기존 리포지토리 이름>:<기존 태그> <변경할 리포지토리 이름>:<변경할 태그>
    
    # tag 변경 후 Docker Hub에 업로드(Docker id 로그인 필요)
    docker tag <기존 리포지토리 이름>:<기존 태그> <Docker id/리포지토리 이름>:<변경할 태그>
    docker push <Docker id/리포지토리 이름>

Docker pull 없이 run을 통해 컨테이너를 만들 수 있다.

  • 단, 이전에 이미지를 실행한 이력이 있으면 이미지의 업데이트 여부를 확인하지 않고 당시 이미지를 기준으로 컨테이너가 실행되기 때문에 업데이트가 있는지 확인이 필요한 경우 pull을 한 뒤 run을 해야한다.

  • Docker 이미지 → 컨테이너 생성 예제

    # f-node 이미지로 컨테이너를 생성하며 포트는 외부 3000번 포트를 통해
    # 내부 80포트로 연결될 수 있도록 설정하고 detach 모드로 실행
    # 생성되는 컨테이너의 이름은 f-app이며 컨테이너가 중지됨과 동시에 컨테이너는 사라진다.
    docker run -p 3000:80 --rm -d --name f-app f-node

볼륨(Volume)

  • 컨테이너의 폴더/파일과 호스트의 폴더/파일의 연결
    • 볼륨이 설정된 경우 컨테이너가 삭제되어도 내부에 있던 데이터들은 호스트의 연결된 폴더에 남아있는다.
  • 이미지 = 읽기 전용
  • 컨테이너 = 읽기, 쓰기 전용
    • 컨테이너가 삭제(Remove)되는 경우 내부 데이터도 함께 사라진다.
  • 익명 볼륨
    • -v VOL_NAME
    • 도커가 자동으로 설정하는 볼륨으로 컨테이너가 중지되면 볼륨도 같이 사라진다.
    • 주로 컨테이너가 동작 중에 임시로 사용해야하는 경우 사용
    • 익명 볼륨을 사용하는 경우 컨테이너가 생성될 때 —rm 옵션을 준 상태에서는 익명 볼륨이 자동으로 사라지지만 아닌 경우에는 볼륨이 그대로 남아있는 상태로 계속 생기기 때문에 docker volume rm VOL_NAME 또는 docker volume prune 을 통해 익명 볼륨을 삭제 해야한다.
  • 네임드 볼륨
    • -v HOST_NAME:VOL_NAME
    • 컨테이너 종료 후에도 유지 가능한 볼륨
    • (리눅스 기준) /var/lib/docker/volumes/<VOL_NAME>/_data 에 위치
    • docker run -v <VOL_NAME>:/tmp:ro --rm -it centos:7
      • 볼륨 지정 시 볼륨 데이터의 권한을 별도로 부여할 수 있다.(default : rw)
    • 하나의 볼륨으로 2개 이상의 컨테이너에서 사용할 경우 동시 읽기 쓰기가 가능한가?
      • 한쪽이 읽을 때 다른쪽에서 쓰기가 가능한지 ?
  • 바인드 마운트
    • -v HOST_ABS_PATH:VOL_NAME
    • -v HOST_ABS_PATH:VOL_NAME:ro : read only 읽기 전용 모드
    • 호스트 머신 상에 매핑될 컨테이너의 경로를 사용자가 직접 지정
    • 파일 단위로 연결 가능
    • 네임드 볼륨과 마찬가지로 -v를 통해 옵션을 주지만 호스트 경로를 부여할 때 절대경로 형태로만 부여가 가능하다
      • 전체 경로 복사가 불편할 경우 아래처럼 대체할 수 있다.
      • Mac/Linux : -v $(pwd):/app
      • Windows : -v "%cd%":/app
    • 호스트에서 수정한 코드나 파일들이 이미지 빌드 필요 없이즉시 컨테이너에 반영
    • 네임드 볼륨과 바인드 마운트가 같이 사용되는 경우 -v 옵션이 2번 들어간다.
    • 파일 하나만 공유하는 것이 아닌 프로젝트 폴더 전체를 공유할 때 주로 사용하며 경로의 특수문자나 공백이 깨지지 않도록 따옴표로 호스트 경로와 컨테이너 경로까지를 묶어주는 것이 좋다.
    • 호스트 파일 시스템의 영향이 크고 모든 폴더에 접근 가능해 보안이 볼륨 지정 방식에 비해 취약하다.
    • 컨테이너 내부에서 생성된 파일의 소유자는 root로 변환된다.
  • 볼륨 설정이 여러개인 경우 도커는 더 상세하고 긴 경로를 우선으로 동작한다.

.dockerignore

  • .git, Dockerfile 등 이미지에 필요 없는 파일을 제외

네트워크

유형

  • BRIDGE
    • 컨테이너의 내부 네트워크
    • 도커 설치 시 docker0 이라는 리눅스 브릿지가 생성
    • 컨테이너별 IP 할당
    • 외부 → BRIDGE 통신 시 포트포워딩 사용
    • 도커 네트워크 Default
    • docker network create --subnet 192.168.100.0/24 --gateway 192.168.100.254 net1
    • docker network inspect <NETWORK NAME>
    • 같은 네트워크를 공유 시 컨테이너 간 통신을 별칭으로 가능
  • HOST
    • 호스트의 네트워크 정보를 공유
    • 컨테이너 간 포트의 중복이 있으면 안된다.
  • None
    • 컨테이너의 네트워크 기능 사용 X
  • overlay
    • 서로 다른 도커 호스트를 연결 가능한 네트워크
    • 도커 스웜과 같은 클러스터 서비스에 사용
  • macvlan
    • MAC 주소를 컨테이너에 할당
    • 호스트와 같은 네트워크 대역의 IP를 할당 받는다.

Connect

  • 브릿지 사이의 연결은 도커에서 지원하지 않는다.
  • docker network connect <NETWORK NAME> <CONTAINER NAME>
    • connect를 사용하면 다른 네트워크와 컨테이너를 연결 할 수 있다.

컨테이너 ↔ 로컬 호스트

  • Docker 컨테이너와 호스트 pc의 통신이 필요할 때 주소에localhosthost.docker.internal 로 대체하면 컨테이너와 호스트의 통신이 가능하다.

컨테이너↔ 컨테이너

  • docker container inspect <CONT_NAME> 을 입력 후 NetworkSettings를 참조하면 해당 컨테이너의 IP를 알 수 있으며 이를 이용해 컨테이너끼리 통신할 수 있다.
  • 단, 해당 IP는 시스템에 따라 달라 질 수 있다.

컨테이너 네트워크 통합

  • 컨테이너 생성 시 --network <NET_NAME> 옵션을 통해 여러 컨테이너를 하나의 네트워크로 묶을 수 있다.
  • 단, 네트워크는 컨테이너 생성 전 미리 docker network create <NET_NAME> 을 통해 도커 내부 네트워크를 만들어 둔 상태로 생성해야 사용이 가능하다.
  • 같은 네트워크로 연결된 컨테이너와 통신 하고 싶을 때에는 localhost(=127.0.0.1) -> <CONT_NAME> 처럼 IP 대신 컨테이너 이름을 넣어주면 네트워크 내부 컨테이너 사이의 통신이 가능하다.

빌드 인수(Arg)와 런타임 환경변수(Env)

  • 빌드 인수(Build Arguments)
    • 이미지와 컨테이너를 동적으로 빌드할 수 있게 만드는 요소
  • 런타임 환경변수(Runtime Environment)
    • 이미지를 빌드하거나 컨테이너 실행 시 외부에서 특정 데이터를 전달
  • docker run -itd -e VARS="HI" --name NAME IMAGE:TAG
    • 컨테이너 실행 시 환경 변수 지정(영구)
  • docker exec -it -e VARS="Hi" NAME
    • 컨테이너 접속 시 환경 변수 지정(임시)

리소스 관리

  • docker stats - 실시간 리소스 확인
    • -a : 모든 컨테이너
    • --no-stream : 스트리밍 X
  • docker top <CONTAINER NAME>
    • 지정한 컨테이너의 top 정보를 확인
    • docker top의 프로세스는 호스트에서 같은 PID로 kill이 가능
  • docker kill --signal=9 my_container
    • 컨테이너 강제 종료(=SIGKILL)
  • 리소스 제한
    • docker run -it --name os --cpus 0.3 centos
      • CPU 자원의 30%
    • docker run -it --name os --memory 1024m centos
      • 메모리 1GB 설정
    • docker run --memory-swap 1024m os
      • 메모리 스왑 설정
      • 메모리 스왑 > 메모리
      • 무제한 스왑을 활성화하려면 -1
      • 실행 중인 컨테이너에는 갱신이 되지 않는다.
      • 메모리 스왑을 확인하고 싶은 경우 컨테이너 inspect가 필요
    • docker update --memory 1024m <CONTAINER NAME>
      • 구동 중인 컨테이너의 메모리 리소스 업데이트

컨테이너 접근 및 실행

  • docker attach - shell이 실행 중인 컨테이너에 접근하고 싶을 때
    • shell이 실행 중인 컨테이너에 접속 후 exit로 빠져나오면 컨테이너가 종료되기 때문에 CTRL+P + CTRL+Q 를 눌러 컨테이너에서 강제 탈출을 할 수 있다.
  • docker exec - 실행 중인 컨테이너에서 명령을 실행
    • docker exec os ip addr show
  • docker diff <CONTAINER NAME> - 컨테이너 파일 변경 상태 체크
    • A : 추가
    • C : 변경
    • D : 삭제

Docker 이미지 관리

  • docker image save/load - 호스트에 저장된 이미지를 아카이브 파일로 복사
    • docker image save -o centos7.tar centos:7
    • docker image save centos:7 > centos7.tar
    • docker image save centos:7 httpd:latest mysql:5.7 > all_image.tar
      • tar tf centos7.tar - tar 의 내용 확인
    • docker image load -i centos7.tar
    • docker image load < centos7.tar
  • docker container commit - 컨테이너를 이미지로 변환
    • docker container commit test_img:0.0.1
      • 리포지토리 이름과 태그를 입력하지 않아도 이미지는 생성되지만 별도의 이름을 부여하지 않아 이미지 ID로만 사용 할 수 있다.
  • docker container import/export - 컨테이너의 파일 시스템을 아카이브 파일로 추출 ↔ 복원
    • docker container export os1 -o export.tar
      • save와는 다르게 tar tf 로 확인 시 / 아래 폴더들의 목록이 확인된다.
    • docker container export os1 > export .tar
    • docker image import export.tar export:0.0.1
      • 파일 시스템만 가져오기 때문에 기타 설정 값은 가져올 수 없다.
        • 이미지를 inspect로 확인 했을 때 config의 cmd 란이 비어있어 실행 불가
        • docker run -itd --name os2 exp:0.0.1 bash 처럼 실행 시 강제로 Shell을 실행하면 작업 가능

Host와 컨테이너 사이의 파일 이동

# Host -> Container로 파일 이동
docker cp <호스트 경로> <컨테이너 이름or컨테이너ID>:<컨테이너 경로>

# Container -> Host 파일 이동
docker cp <컨테이너 이름or컨테이너ID>:<컨테이너 경로> <호스트 경로> 

Dockerfile

지시어

지시어설명
FROM베이스 이미지 지정
ENV컨테이너 환경 변수 지정
WORKDIR컨테이너 작업 디렉토리 지정
EXPOSE컨테이너 포트 지정
ADD이미지 생성 시 파일 추가(상대경로)
ENTRYPOINT컨테이너의 애플리케이션 지정
LABEL이미지 메타데이터 추가
USER컨테이너 사용자 지정(이미지 내 유저가 사전생성되어야 함)
RUN작업할 명령 지정
VOLUME컨테이너 볼륨 지정
COPY이미지 생성 시 파일 복사
CMD컨테이너의 애플리케이션 지정
  • ENTRYPOINT, CMD는 하나만 존재할 경우 역할이 같으며 같이 있게 되면 ENTRYPOINT가 명령어, CMD가 ARGUMENT로 사용된다.

Dockerfile 실습

# rocky9 리눅스에서 http 서비스를 실행 했던 순서
dnf install -y httpd
vi /etc/httpd/conf/httpd.conf
vi /var/www/html/index.html
systemctl start httpd
firewall-cmd --add-service=http
  • 설정 파일의 변경 작업은 Dockerfile에서 구현하기 힘들기 때문에 미리 file을 준비해 대체하거나 볼륨으로 처리 후 수정도 가능
  • 컨테이너 환경에서는 방화벽 설정을 하지 않음
  • 대화형 작업이 있는 경우 대화 작업을 무시하고 작업할 수 있는 방법으로 구현한다.
  • Docker는 단일 프로세스 위주 설계로 systemd 같은 프로세스 관리자를 이미지에 포함시키지 않는다.
FROM centos:7
RUN yum install -y httpd
VOLUME /etc/httpd/conf.d
EXPOSE 80/tcp
COPY index.html /var/www/html
WORKDIR /var/www/html
CMD /usr/sbin/httpd -D FOREGROUND # 컨테이너에서 systemctl 제한

이미지 레지스트리

  • Docker Registry
    • 기존 Docker 허브 사용 시 썼던 유저이름이 localhost:5000(기본값)으로 대체
    • docker pull registry:2
    • docker run -d -p 5000:5000 --name registry registry:2
    • docker image tag centos:latest localhost:5000/mycentos:v1 - 이미지 태그 변경
    • docker push localhost:5000/mycentos:v1 - 이미지 업로드
  • Harbor 저장소
    • 하드웨어 최소 사양 이상, Docker compose 설치가 된 상태에서 설치 가능
    • Harbor 공식 Github에서 최신 릴리즈 버전의 아카이브 파일 링크를 복사 후 wget으로 설치
    • 다운로드 한 harbor 아카이브 압축 해제
    • 압축 해제한 harbor 폴더 내 harbor.yml.tmpl 을 harbor.yml로 복사 후 세팅 후 저장
      • hostname은 호스트의 이름 또는 IP 를 사용
      • 실습 시 HTTPS를 생략해 harbor.yml 제거
        • HTTPS 생략 시 /etc/docker/daemon.json 이라는 파일 추가
          • daemon.json - { "insecure-registries" : ["<HOST IP>"] }
          • 이미지 저장소 접근 시 443포트가 아닌 80포트로 접근 하기 위함
    • sudo systemctl restart docker
    • sudo ./install.sh
    • docker login <HOST IP> - 성공 시 Login Succeeded 를 확인할 수 있다.
    • docker tag centos:latest <HOST IP>/libriry/docker:centos 이미지 태그 변경
      • harbor에서는 이미지:태그 가 아니라 태그= 이미지+태그 이기 때문에 사용자가 알아서 구분할 수 있게 이름을 지어야 한다.
    • docker push <HOST IP>/library/docker:centos 이미지 업로드

어플리케이션 빌드 실습

  • Go 기반의 어플리케이션 Dockerfile 작성
    • golang 이미지를 이용한 go 파일 실행
      FROM golang
      COPY hello.go .
      RUN go build hello.go
      CMD go run hello.go
  • 빌드한 결과 파일만을 가지고 이미지 용량을 최소화
    • Go 같은 컴파일 언어는 빌드한 실행 파일이 존재할 때 scratch 이미지를 사용해 용량을 최소화 하면서 같은 결과를 사용할 수 있다.

      FROM scratch
      WORKDIR /app
      COPY hello .
      CMD ./hello
  • 멀티 스테이징을 이용해 위 2개의 Dockerfile 작성을 한번에 진행
    FROM golang AS build
    COPY hello.go .
    RUN go build hello.go
    
    FROM scratch
    COPY --from=build /go/hello /
    CMD ./hello

Docker-Compose

  • Docker vs Docker-compose vs Kubernates
    • Docker : 하나의 호스트에서 컨테이너 및 오브젝트를 하나씩 배포/구성
    • Docker-compose : 하나의 호스트에서 하나 이상의 컨테이너들을 일괄적 배포 / 관리
    • Kubernates : 여러 개의 호스트에서 하나 이상의 컨테이너를 일괄적 배포 / 관리
  • 여러 컨테이너의 Image 생성과 컨테이너 생성 시 복잡한 명령어를 여러번 입력하는 것을 편하게 하기 위해 나온 아이디어
  • 하나의 호스트에서 관리하는 컨테이너가 여러개일 때 유용
    • 다수의 호스트에서 다수의 컨테이너를 관리에는 장점 X
  • Services(=Containers)
  • docker-compose를 사용해 서비스가 시작되면 기본적으로 detach 모드로 실행되고 서비스가 종료되면 자동으로 서비스가 사라진다.
  • docker-compose.yaml 설정 예시
version: "3.8"
services:
	<SERVICE1>:
		image: <IMG_NAME>
		volumes:
			- <SERVICE_PATH> # Anonymous volume
			- <HOST_PATH>:<SERVICE_PATH> # Named volume
		environment:
			- <ENV_NAME1>:<VAR1>
			- <ENV_NAME2>:<VAR2>
		env_file:
			- <RELATIVE PATH> # docker-compose.yaml 기준의 상대 경로
		ports:
		# 포트번호가 1개만 입력되는 경우 내부포트 설정
			- '80:80' 
		depends_on:
			# 해당 서비스가 다른 서비스에 의존성을 가질 경우 표기
			- <SERVICE_NAME>
			- ...
		# -i
		stdin_open: true 
		# -t
		tty: true
		# 컨테이너의 이름을 직접 짓고 싶을 떄 사용
		container_name: <VAR_NAME> 

	<SERVICE2>:
		build:<REALTIVE PATH> #이미지를 빌드하기 위한 Dockerfile의 경로
		...
volumes:
	<VOL_NAME>: # Named volume만 기재
  • Docker-Compose 실행/종료
    • docker-compose.yaml 이 있는 경로에서 터미널을 이용해 docker-compose up 을 입력하면 서비스가 실행되며 docker-compose up -d 를 하면 서비스를 백그라운드에서 실행할 수 있다.
    • docker-compose down 을 입력하면 서비스가 종료되며 docker-compose down -v 를 입력하면 서비스에서 생성됐던 볼륨까지 같이 삭제가 된다.

Docker-compose reference

  • Docker-compose 관련 명령어는 docs.docker.com의 reference의 compose 부분을 참조해서 확인하면 된다.

Docker-compose 실습

  1. HTTP + DB

    name: compose_test
    services:
      web01:
        image: httpd
        scale: 2 # container_name: webserver # scale 시 container_name을 사용 할 수 없음
        ports:
          - 80 # port 포트포워딩이 외부까지 세팅 된 경우 포트가 겹쳐 scale 불가
      dbserver:
        container_name: database
        image: mysql:5.7
        ports:
          - 3306
        environment:
          MYSQL_ROOT_PASSWORD: 123
        volumes:
          - type: volume
            source: db-data
            target: /var/lib/mysql
          # - db-data:/var/lib/mysql
    
    volumes:
      db-data:
    • docker-compose scale <SERVICE NAME>=N : 특정 서비스를 N개 만큼 생성
      • 포트가 중첩 되는 경우 정상적인 스케일 동작을 안하니 주의
      • docker-compose.yaml 의 scale 에 수를 추가해도 동일
  2. WordPress + MYSQL

    1. docker 컨테이너를 이용한 실습

      1. MYSQL

        docker run --name db --network wp-net -p 8080:80 -v db-vol:/var/lib/mysql -d \   ✔  vagrant@rocky9 
        > -e MYSQL_ROOT_PASSWORD=123 -e MYSQL_USER=wp-user -e MYSQL_PASSWORD=123 \
        > -e MYSQL_DATABASE=wp-db mysql:5.7
      2. WordPress

        docker run -d --name wp --network wp-net -v wp-vol:/var/www/html \
        -e WORDPRESS_DB_USER=wp-user -e WORDPRESS_DB_PASSWORD=123 -e WORDPRESS_DB_NAME=wp-db \
        -e WORDPRESS_DB_HOST=db wordpress
    2. docker-compose.yaml 로 구현

      version: '3.1'
      services:
        wordpress:
          container_name: wp
          image: wordpress
          restart: always
          ports:
            - 8080:80
          environment:
            WORDPRESS_DB_HOST: db
            WORDPRESS_DB_USER: wp-user
            WORDPRESS_DB_PASSWORD: 123
            WORDPRESS_DB_NAME: wp-db
          volumes:
            - wp-vol:/var/www/html
          depends_on:
            - db
          networks:
            - wp-net
      
        db:
          container_name: db
          image: mysql:5.7
          restart: always
          environment:
            MYSQL_DATABASE: wp-db
            MYSQL_USER: wp-user
            MYSQL_PASSWORD: 123
            MYSQL_RANDOM_ROOT_PASSWORD: '1'
          volumes:
            - db-vol:/var/lib/mysql
          networks:
            - wp-net
      
      volumes:
        wp-vol:
        db-vol:
      
      networks:
        wp-net:

0개의 댓글