1. 도커의 기본 개념
도커(Docker):
도커는 운영체제 위에서 동작하는 프로그램으로, 경량화된 가상 머신(Virtual Machine)으로 생각할 수 있다. 가장 큰 차이는 가상 머신이 운영체제까지 가상화하는 반면 도커는 호스트 운영체제를 그대로 활용한다. 도커는 이미지를 기반으로 컨테이너를 실행하며, 컨테이너는 격리된 환경에서 동작하여 이식성이 뛰어나다.
// VMware같은 가상머신과 비슷한 개념
Dockerfile:
커스텀 이미지를 생성하기 위한 텍스트 파일로, 특정 명령어를 실행하거나 호스트 파일을 복사하는 등의 작업을 정의한다. Dockerfile을 사용하여 도커 이미지를 빌드하고 정의할 수 있다.
// 도커
커스텀
이미지를 생성하기 위한 파일 (커스텀이라는 부분이 중요함)
// 기존 이미지를 이용해 작성순서등을 변경한 커스텀 이미지 파일을 만듬
이미지(Image):
도커에서 프로그램을 빌드, 실행, 배포하기 위한 모든 것을 포함하는 패키지이다. 이미지는 소스 코드, 라이브러리, 런타임 등을 정의하며, Dockerfile을 통해 이미지를 정의하고 빌드할 수 있다. 이미지는 컨테이너에 올라가 실행된다.
// 해당 이미지로 컨테이너를 만든다
// VMware에 들어가는 이미지와 비슷한 개념
컨테이너(Container):
도커 이미지가 실행되는 단위로, 호스트와 격리된 상태에서 동작한다. 도커 이미지와 함께 있으면 어느 환경에서든 실행 가능하며, 가상화된 환경에서 독립적으로 동작한다.
도커 컴포즈(Docker Compose):
여러 컨테이너를 하나의 서비스로 다루기 위한 개념으로, 이미지 하나에 필요한 소프트웨어 및 환경을 정의한다. 도커 컴포즈를 사용하면 여러 컨테이너 간의 관계와 설정을 쉽게 관리할 수 있다. 컴포즈 파일을 통해 서비스를 정의하고 실행할 수 있다.
// 여러 컨테이너를 하나의 서비스로 다루기 위함
DockerFile을 이용해서 커스텀 이미지로 build하는것과, 일반 이미지로 빌드하는것의 차이와 흐름설명 (중요)
Dockerfile 사용해서 커스텀 이미지로 빌드시
Docker-comopse.yml에 기재된 build항목에서 Dockerfile의 로컬 위치를 찾아서 읽음 → Dockerfile에 기재된 이미지 파일을 DockerHub 에서 pull Image → Dockerfile에 기재된 순서와 방법따라서 빌드 → 커스텀 이미지 생성완료→ 이미지로 컨테이너 생성 → 여러 컨테이너를 도커 컴포즈로 제어
참고파일
docker-comopse.yml
services: myservice: container_name: myapp build: dockerfile/path # dockerfile이 있는 경로 지정
DockerFile
Dockerfile FROM node:18-slim # 도커 허브로 부터 받아올 이미지 ENV TZ Asia/Tokyo # 커스텀 이미지를 만들며 설정할 옵션
Dockerfile 사용하지 않고 일반 이미지로 빌드시
Docker-comopse.yml에 기재된 image항목을 찾음 → 해당 이미지 파일을 DockerHub 에서 pull Image → 일반 이미지 생성완료→ 이미지로 컨테이너 생성 → 여러 컨테이너를 도커 컴포즈로 제어
참고파일
docker-compose.yml
services: myservice: image: nginx:1.25.0 # 도커허브로 부터 받아올 이미지
2.명령어 리스트
1. 기본명령
docker image ls // 이미지 조회
docker ps -a // 컨테이너 모두 조회
2. 도커 허브에서 이미지 가져오는 방법 혹은 커스텀 이미지 생성하는 방법
2-1 도커 이미지 pull
docker image pull 레파지토리명[:태그명]
2-2 도커 커스텀 이미지 만들기(빌드)
docker image bulid -t 이미지명[:태그명] Dockerfile경로
// 이미지를 pull해서 새로운 이미지를 생성한다
// -t 명령어는 이미지의 태그명을 추가함
// 태그명을 미지정시 latest로 자동지정
3. 컨테이너 시작
docker start 컨테이너ID
4. 컨테이너 접속
4-1 컨테이너 접속
docker attach 컨테이너ID
4-2 실행되고 있던 컨테이너 접속
docker exec -it 컨테이너ID /bin/bash // -it 명령어는 터미널 기능활성화후 접속
5. 컨테이너 생성 및 시작
docker run 이미지태그명 // 새로운 컨테이너 생성 후 실행
6. 컨테이너 생성 및 시작 및 접속
docker run -it 이미지태그명 // 이미지 생성된 컨테이너 시작
7. 컨테이너 삭제
docker rm 컨테이너ID
3. DockerFile에 요소에 대해서
FROM
: 빌드할 베이스 이미지를 지정. 이미지가 로컬에 없으면 도커 허브에서 해당 이미지를 검색해 다운. ex) FROM ubuntu:latest
RUN
: 컨테이너에서 실행할 명령어를 지정. 보통 컨테이너에 필요한 라이브러리를 다운받는 명령어나 디렉토리를 만드는 명령어를 지정한다. ex) RUN apt-get update
ADD (COPY명령어와 동일)
: 컨테이너에서 배치할 파일이나 디렉토리를 지정. ex) ADD ./message /message ===> 해당 명령어는 현재 디렉토리에 위치한 message라는 파일을 컨테이너의 루트 디렉토리에 message라는 이름으로 배치하라는 소리다.
CMD
: 컨테이너가 시작할 때 실행할 명령어를 지정. RUN은 이미지를 빌드할 때 실행되고 CMD는 이미 빌드된 이미지(컨테이너)가 시작할 때 실행된다. 여러 CMD는 모두 실행되지 않고 맨 마지막 CMD만 실행된다.
ENTRYPOINT
: CMD와 동일. 하지만 CMD에서는 param값을 대체할 수 있지만 ENTRYPOINT는 불가능하다. ENTRYPOINT와 CMD는 같이 쓰이면서 CMD는 default값을 가진 param을 갖는 명령어를 지정할 때 쓰이고 ENTRYPOINT는 그렇지 않을 때 쓰인다. 또한 CMD와 마찬가지로 여러 ENTRYPOINT는 모두 실행되지 않고 맨 마지막 ENTRYPOINT만 실행된다.
LABEL
: key-value 형식의 메타데이터를 이미지에 추가.
ENV
: LABEL과 동일하지만 메타데이터 대신 환경변수를 설정.
VOLUME
: 컨테이너 내의 특정 디렉토리를 지정. 해당 디렉토리를 외부 경로에 마운트되어 컨테이너가 삭제되어도 해당 디렉토리의 정보는 보존될 수 있게 됨.
외부 경로란 HOST OS의 /var/lib/docker/volumes 경로를 의미한다.
서로 다른 서비스(컨테이너)에서 동일한 디렉토리(데이터)를 공유하는법
version: '3'
services:
service1:
image: your-service1-image
volumes:
- .:/path/to/shared/directory # 디렉토리가 service2와 동일하다
service2:
image: your-service2-image
volumes:
- .:/path/to/shared/directory
WORKDIR
: 이 명령어는 현재 작업 디렉토리를 변경하고, 이후의 명령어들이 해당 디렉토리에서 실행되도록 설정 ( linux의 cd명령어와 동일)
Dockerfile에 아래와 같이 적혀있다면
cd /var/www한 후에 거기서 composer require google/apiclient:~2.0 라는 컴포저 패키지를 설치하라는 말이다
WORKDIR /var/www
RUN composer require google/apiclient:~2.0
DockerFile의 예제
FROM ubuntu:latest // ubuntu:latest 이미지를 로컬에서 먼저 찾아봄. 없으면 docker hub에서 해당 이미지 찾아서 다운
MAINTAINER myname // 관리자설정하며 myname이라는 사람을 관리자로 설정
RUN apt-get install -y // 이미지 빌드시 apt-get install명령어 실행
ADD testfile1 /testfile2 // 현재로컬에 있는 testfile1폴더를 컨테이너의 루트폴터에 testfile2라는 이름으로 복사함
VOLUME /mountcheck 컨테이너에 mountcheck라는 폴더를 생성하고 로컬PC에도 해당 공유폴더를 위치시킴
4. PHP + Apache의 도커 환경설정
1. 아래 파일 생성
[Dockerfile]
FROM php:8.2-apache
COPY . /var/www/html
[index.php]
<?php
phpinfo();
?>
2.아래 명령어 실행
docker build -t docker-php .
// 현재 폴더에서 dockerfile을 가지고 커스텀 이미지를 생성한다
docker run -d -p 0.0.0.0:53333:80 docker-php
// 로컬(호스트PC)의 모든 IP(0.0.0.0)에서 53333포트로 접근시 컨테이너에 80포트로 연결된다
// 1.1.1.1:53333 으로 접근해도 phpinfo()화면이 보임
docker exec -it 컨테이너ID /bin/bash
// 해당 컨테이너에 접속한다
which php // php설치한곳확인
php --ini // php.ini위치확인
docker-php-ext-install mysqli && docker-php-ext-enable mysqli // 도커기반 php의 extension설치
+ 추가 상세내용은 참조를 확인
5. Docker-compose를 이용한 PHP+Apache+Mysql설정
Dockerfile
FROM php:7.3.3-apache # php7.3이미지를 도커허브로부터 pull
RUN docker-php-ext-install mysqli # docker용 php extension설치
EXPOSE 80 # 80번포트를 컨테이너로부터 개방
Dockercompose
// 컨테이너끼리 서로 통신한다
version: '3.3'
services:
web: # 컨테이너명1 (php/apache)
build:
context: .
dockerfile: Dockerfile
depends_on:
- db
volumes:
- ./:/var/www/html/
ports:
- 80:80
db: # 컨테이너명2 (Mysql)
container_name: mysql8
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_DATABASE: db
MYSQL_USER: admin
MYSQL_PASSWORD: admin
MYSQL_ROOT_PASSWORD: admin
phpmyadmin:
image: phpmyadmin/phpmyadmin:4.7
depends_on:
- db
ports:
- "89:80"
environment:
- "PMA_HOST=db"
- "PMA_USER=admin"
- "PMA_PASSWORD=admin"
docker-compose로 주로 사용하는 명령어
docker-compose up -d // docker-compose.yml을 참조해서 컨테이너를 생성하고 실행한다 (최초에 이미지가 없으면 빌드해준다)
docker-compose down // docker-compose로 생성된 컨테이너를 정지하고 삭제한다
docker-compose up -d --build // docker-compose.yml을 참조해서 이미지를 재빌드하고 컨테이너를 생성하고 실행한다 (dockerfile등의 이미지에 수정사항이 있을 경우 사용)
6. Docker-compose를 이용한 Vue3 + flask설정
상세정보는 아래의 깃허브에 있다
version: '3.8' # docker의 버전정보
services:
backend:
restart: unless-stopped
build:
context: ./backend
dockerfile: Dockerfile
command: flask run --port=5000 --debug # 컨테이너가 실행되고 실행될 명령어
volumes:
- ./backend:/backend
ports:
- "5005:5000"
environment:
FLASK_APP: /backend/app.py
FLASK_RUN_HOST: 0.0.0.0
FLASK_CONFIG: local
frontend:
restart: unless-stopped # 정지없이 실행
build:
context: ./frontend
dockerfile: Dockerfile
user: "node"
command: /bin/bash -c "npm install && npm run dev" # 포트개방을 위한 --host 명령은 package.json의 dev명령에 추가함
depends_on:
- backend
volumes:
- ./frontend:/frontend
ports:
- "5555:5173" # 5173포트를 사용하자 6000번 포트사용시 안전하지않다고 경고뜸
host.docker.internal에 대해서
하나의 컨테이너가 있다
그리고 하나의 컨테이너 내부(호스트머신)에서 웹서버(8080포트)와 mysql(3306)이 서로 통신을 하는 상황이다
로컬PC의 경우는 localhost:8080 , localhost:3306을 통해서 서로 통신할수있다
그러나 호스트머신(도커 컨테이너 내부)은 내부에서는 localhost를 사용할수없다.
그래서 host.docker.internal:8080 , host.docker.internal:3306으로 서로 통신해야한다
참조