[docker] 도커 사용방법

컨테이너 띄워보기

사용법

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

컨테이너 실행하기

docker run -it -d -p 8080:80 php:8.1-apache

위 명령어를 실행하면 도커는 php:8.1-apache 이미지가 없다면 pull 받아 컨테이너를 실행함

  • -it : -i옵션과 -t옵션을 같이 쓰이는 경우가 많음
    컨테이너를 실행한 후 컨테이너의 쉘이나 cli도구를 사용할때 쓰임
  • -d : 컨테이너를 백그라운드 모드로 실행
  • -p : 포트바인딩 local : containere
  • php:8.1-apache 컨테이너에 사용할 도커이미지
  • docker run | Docker Documentation

생성된 컨테이너 확인

docker ps  

컨테이너 자세히보기

docker inspect <CONTAINER ID>

컨테이너 이미지 빌드하기

  1. Dockerfile 작성
FROM php:8.1-apache
ENV FOO=bar 
WORKDIR /var/www/html
COPY . .
RUN apt-get update && install -y vim
  1. 이미지 빌드하기
    사용법
docker build [OPTIONS] PATH | URL | -

빌드하기

docker build -t myphp .

Dockerfile 수정이 있으면 위 명령어를 통해서 다시 빌드하면 됨

  • -t 이미지 태그 설정

빌드된 이미지 확인

docker image ls
  1. 컨테이너 생성하기
docker run -it -d --name my_php -p 8080:80  myphp
  • --name 옵션이 없는 경우 컨테이너 이름 랜덤 생성됨

컨테이너 터미널접속하기

docker exec -it <CONTAINER ID> /bin/bash

docker volume

컨테이너에서 생성한 파일은 컨테이너를 삭제하게 되면 같이 삭제 되므로 로컬저장소와 컨테이너저장소를 바인딩할 필요가 있다.

볼륨을 관리하는 방법 : Use bind mounts | Docker Documentation

  1. Named vlolumes
    사용법
docker volume create [OPTIONS] [VOLUME]

볼륨생성

docker volume create myVolume

볼륨마운트

docker run -dp 8080:80 -w /var/www/html -v "myVolume:/var/www/html" php:8.1-apache 

불륨정보확인

docker volume inspect myVolume
{
        "CreatedAt": "2021-12-08T14:16:18Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/myVolume/_data",
        "Name": "myVolume",
        "Options": {},
        "Scope": "local"
    }

볼륨정보를 보면 Mountpoint 에 지정된 경로가 컨테이너에 마운트되는 것을 확인 할수 있다.

Ubuntu, centos 환경에서 /var/lib/docker/volumes/ 에 접근할 수있지만 맥환경에서는 해당 경로가 존재하지 않는다.

맥에서 도커는 가상머신을 사용하기 때문이라는것 같은데 Mountpoint 접근 방법과 자세한 내용은 아래 링크를 참조

Mac에서 docker volume 위치

  1. Bind mounts
    불륨생성할 필요 없이 마운트할 경로를 입력해준다.
docker run -dp 8080:80 -w /var/www/html -v "your/path:/var/www/html" php:8.1-apache 

networks

사용법

docker network create [OPTIONS] NETWORK

네트워크생성

docker network create myphp

네트워크를 연결한 Mysql 컨테이너생성

docker run -d \
--network myphp --network-alias mysql \
-v myVolume:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myphp \
mysql:5.7

mysql 컨테이너 실행

docker exec -it <mysql-container-id> mysql -u root -p

네트워크를 연결한 php컨테이너 mysql 연결하기

 docker run -dp 8080:80 \
   -w /var/www/html -v "$(pwd):/var/www/html" \
   --network myphp \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=root \
   -e MYSQL_PASSWORD=secret \
   -e MYSQL_DB=myphp \
   php:8.1-apache 
docker exec -it <myphp-container-id> /bin/bash
  • MYSQL_HOST=mysql : --network-alias 를 mysql 로 지정했기 때문에 호스트를 네트워크별칭으로 넣어줌
dig MYSQL_HOST
; <<>> DiG 9.16.22-Debian <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30839
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mysql.                IN  A

;; ANSWER SECTION:
mysql.            600 IN  A   172.18.0.2

;; Query time: 1 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Wed Dec 08 15:07:17 UTC 2021
;; MSG SIZE  rcvd: 44

Mysql 컨테이너와 myphp컨테이너에서
dig mysql 명령어를 실행해보면 각각의 컨테이너가 생성한 네크워크를 사용하는 것을 확인 할 수 있다.

myphp 컨테이너에서는 MYSQL_HOST 에 네트워크 별칭을 선언했으므로 dig MYSQL_HOST 으로도 사용 가능하다.

docker compose 사용하기

1개의 서비스에 사용되는 컨테이너가 여러개이고 각각의 옵션이 복잡해진다면 이를 관리하기 힘들어 질것이다.

docker compose 를 사용하면 이러한 문제를 쉽게 해결 할수 있다.

설치확인

docker-compose version

설치문서 : Install Docker Compose | Docker Documentation
맥과 윈도우 환경에서는 별도의 설치가 필요 없다. 만약 docker compose 명령어를 존재하지 않는다는 메시지가 보인다면 루트권한으로 실행하면 된다.

Compose file 생성

  1. 루트 디렉토리에 docker-compose.yml 을 생성해야한다.
  2. 파일을 열고 버전을 명시해준다.
version: "3.7"
  1. 다음으로 사용할 서비스의 목록을 정의한다.
services:

서비스 정의
앞서 네트워스를 설명했던 2개의 커맨드를 docker-compose.yml 에 정의를 할것이다.

우선 두개의 명령어를 가져와 보자면 아래와 같다.
php

 docker run -dp 8080:80 \
   -w /var/www/html -v "$(pwd):/var/www/html" \
   --network myphp \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=root \
   -e MYSQL_PASSWORD=secret \
   -e MYSQL_DB=myphp \
   php:8.1-apache 

mysql

docker run -d \
--network myphp --network-alias mysql \
-v myVolume:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myphp \
mysql:5.7

파일작성하기

version: "3.7"

services:
  myphp:
    build:
      context: . # Dockerfile 경로
    container_name: php-web # 컨테이너 이름
    networks:
      mysql: #network aliase
    ports:
      - 8080:80
      - 8081:443
    volumes:
      - ./web_data:/var/www/html
    environment:
      - MYSQL_HOST=mysql #mysql is network aliase
      - MYSQL_USER=root
      - MYSQL_PASSWORD=secret
      - MYSQL_DB=myphp
  mysql:
    image: mysql:5.7
    container_name: php-mysql
    networks:
      mysql:
    volumes:
      - myVolume:/var/lib/mysql/
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=myphp

volumes:
  myVolume:

networks:
  mysql: #network aliase
    driver: bridge
    name: myphp #netwrok name (docker network ls 로 확인됨)

네트워크대신 link 지정하기
myphp 컨테이너와 mysql 컨테이너는 생성한 mysql 네트워크를 이용해서 서로 접근이 가능하게 처리했다.

이를 좀더 간단하게 처리하려면 컨테이너를 연결하는 link 옵션을 추가하면된다.

version: "3.7"

services:
  myphp:
    build:
      context: . # Dockerfile 경로
    container_name: php-web # 컨테이너 이름
    ports:
      - 8080:80
      - 8081:443
    volumes:
      - ./web_data:/var/www/html
    environment:
      - MYSQL_HOST=mysql #mysql is network aliase
      - MYSQL_USER=root
      - MYSQL_PASSWORD=secret
      - MYSQL_DB=myphp
    links:
      - mysql
  mysql:
    image: mysql:5.7
    container_name: php-mysql
    volumes:
      - myVolume:/var/lib/mysql/
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=myphp

volumes:
  myVolume:

mysql 접속 예제

$host='mysql';
$user='root';
$password='secret';
$dbname='myphp';
$mysqli = new mysqli($host, $user, $password, $dbname);
var_dump($mysqli);
  • $host='mysql'
    • network 를 사용한 경우 컨테이너 아이피 대신 network aliase 를 지정해서 사용할수 있음
    • link를 사용한 경우 컨테이너 아이피 대신 서비스 이름을 지정해서 사용할수 있음

컨테이너 고정아이피 지정하기
컨테이너에 고정아피를 사용해야하는 경우에는 어떻게 할까 ?
네트워크 설정에 ipam 를 정의한 뒤 각 서비스에 고정 아이피를 할당해주면 된다.

version: "3.7"

services:
  myphp:
    build:
      context: . # Dockerfile 경로
    container_name: php-web # 컨테이너 이름
    networks:
      mysql: #network aliase
        ipv4_address: 172.20.0.2
    ports:
      - 8080:80
      - 8081:443
    volumes:
      - ./web_data:/var/www/html
    environment:
      - MYSQL_HOST=mysql #mysql is network aliase
      - MYSQL_USER=root
      - MYSQL_PASSWORD=secret
      - MYSQL_DB=myphp
  mysql:
    image: mysql:5.7
    container_name: php-mysql
    networks:
      mysql:
        ipv4_address: 172.20.0.3
    volumes:
      - myVolume:/var/lib/mysql/
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=myphp

volumes:
  myVolume:

networks:
  mysql: #network aliase
    driver: bridge
    name: myphp #netwrok name (docker network ls 로 확인됨)
    ipam:
      config:
        - subnet: 172.20.0.0/24
          gateway: 172.20.0.1

변수사용하기
루트 디렉토리에 .env을 추가후 변수를 정의하면 docker-compose.yml 에서 사용할수 있다.

도커파일 디렉토리구조

  • project dir
    • Dockerfile
    • docker-compose.yml
    • .env

.env

...
MYSQL_PASSWORD=yourpassword
...

변수의 사용

...
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
...