[Docker] 도커
들어가며
해당 게시글은 인프런 subicura 강사님의 초보를 위한 도커 안내서 강의를 바탕으로 쓰였음을 미리 밝힙니다.
도커란 무엇인가
서버를 관리한다는 것
- 도커는 컨테이너 기반의 오픈소스 가상화 플랫폼이다.
- Oracle, Wordpress, Gitlab 등 매우 복잡하다.
- AWS, Azure, Google Cloud 등 계속해서 바뀌는 서버 환경
- Node.js, Python, Ruby 등 계속해서 바뀌는 개발 환경
서버관리 방식의 변화
- 전통 방식: Add user -> System Env -> Firewall -> Network -> dependencies -> Python -> Git clone -> Package -> Configuration -> Migration -> Proxy -> Run (한땀한땀 관린 필요)
- 하나의 단계에서라도 사소한 문제 발생시 서버가 죽게 된다.
- 도커의 경우 어떠한 프로그램도 컨테이너로 만들 수 있고 어디서든 돌아간다.
- 가상머신처럼 독립적으로 실행되지만 가상머신보다 빠르고 가상머신보다 쉽고 가상머신보다 효율적이다.
도커의 등장
- 서버를 관리하기 위한 노력
- 서버배포.pptx -> 문서화 한다
- 상태관리 도구(CHEF, puppet, ANSIBLE)
- 가상머신
- 자원격리: 프로세스를 가상으로 분리, 파일 / 디렉토리를 가상으로 분리, CPU / MEMORY / IO 그룹별 제한(리눅스 커널의 기능을 이용한 빠르고 효율적인 서버 관리)
- 도커의 등장
- 컨테이너: 격리된 환경에서 작동하는 가상의 프로세스
- 리눅스 커널의 여러 기술을 활용
- 하드웨어 가상화 기술보다 가벼움
- 이미지 단위로 프로세스 실행 환경을 구성
도커란

- 도커의 특징: 확장성 / 이식성 / 표준성 / 이미지 / 설정관리 / 자원관리
- 도커가 설치되어 있다면 어디서든 컨테이너를 실행할 수 있음
- 특정 회사나 서비스에 종속적이지 않음
- 쉽게 개발서버를 만들 수 있고 테스트서버 생성도 간편함
- 컨테이너라는 표준으로 서버를 배포하므로 모든 서비스들의 배포과정이 동일해짐
- 이미지에서 컨테이너를 생성하기 때문에 반드시 이미지를 만드는 과정이 필요
- Dockerfile를 이용하여 이미지를 만들고 처음부터 재현 가능
- 빌드 서버에서 이미지를 만들면 해당 이미지를 이미지 저장소에 저장하고 운영서버에서 이미지를 불러옴
- 설정은 보통 환경변수로 제어함
- MYSQL_PASS=password와 같이 컨테이너를 띄울때 환경변수를 같이 지정
- 하나의 이미지가 환경변수에 따라 동적으로 설정파일을 생성하도록 만들어져야함
- 컨테이너는 삭제시 모든 데이터가 초기화됨
- 업로드 파일의 경우 별도의 저장소 필요
- 세션이나 캐시를 redis 와 같은 외부로 분리 —> 컨테이너: 서버 관리 혁신
컨테이너의 미래
- 여러대의 서버와 여러개의 서비스를 관리하기 쉽게(쿠버네티스)
- 스케쥴링
- 컨테이너(서비스 프로세스)를 적당한 서버에 배포해 주는 작업
- 전략: idle 서버에 배포, 순서배포, 랜덤배포
- 서버가 죽으면 실행중이던 컨테이너를 다른 서버에 띄어줌
- 클러스터링
- 여러 개의 서버를 하나의 서버처럼 사용(컨테이너 사이의 통신)
- 흩어져 있는 여러 개의 컨테이너도 가상 네트워크를 이용하여 마치 같은 서버에 있는 것처럼 쉽게 통신
- 서비스 디스커버리
- 서비스를 찾아주는 기능
- 클러스터 환경에서 컨테이너는 어느 서버에 생성될지 알 수 없고 다른 서버로 이동할 수도 있음
- 컨테이너와 통신을 하기 위해서 어느 서버에서 실행중인지 알아야 하고 컨테이너가 생성되고 중지될 때 어딘가에 IP와 Port같은 정보를 업데이트해줘야 함
- key-value 저장소에 정보를 저장할 수도 있고 내부 DNS 서버를 이용
도커 - 설치부터 실행까지
도커 설치하기

- 도커는 기본적으로 linux를 지원하기 때문에 MacOS와 Windows에 설치되는 Docker는 가상머신에 설치됨
- MacOS는 xhyve를 사용하고 Windows는 Hyper-V 사용
- docker CLI 는 도커 호스트에 명령을 전달하고 겨로가를 받아서 출력함
도커 기본 명령어(run)

docker run ubuntu:20.04
- run 명령어를 사용하면 사용할 이미지가 저장되어 있는지 확인하고 없다면 다운로드 (pull) 한 후 컨테이너를 생성(create)하고 시작(start)한다. 컨테이너는 정상적으로 실행됐지만 뭘 하라고 명령어를 전달하지 않았기 때문에 컨테이너는 생성되자마자 종료된다. 컨테이너는 프로세스이기 때문에 실행중인 프로세스가 없으면 컨테이너는 종료된다.
- 이미지마다 컨테이너가 만들어질때 실행할 명령어를 지정할 수 있고 ubuntu:20.04는
/bin/sh
가 지정되어 쉘이 실행되야 하지만, 입력을 받을 수 있도록-it
옵션을 입력하지 않았기 때문에 바로 실행이 종료되었다.
docker run --rm -it ubuntu:20.04 /bin/sh
- 컨테이너 내부에 들어가기 위해
sh
를 실행하고 키보드 입력을 위해-it
옵션을 준다. 추가적으로 프로세스가 종료되면 컨테이너가 자동으로 삭제되도록--rm
옵션도 추가한다.--rm
옵션이 없다면 컨테이너가 종료되더라도 삭제되지 않고 남아 있어 수동으로 삭제 해야한다.
- 컨테이너 내부에 들어가기 위해
docker run --rm -it centos:8 /bin/sh
- 도커는 다양한 리눅스 배포판을 실행할 수 있다. 공통점은 모두 동일한 커널을 사용한다는 점이다. Ubuntu 또는 CentOS에 포함된 다양한 기본기능이 필요 없는 경우, Alpine 이라는 초소형 (5MB) 이미지를 사용할 수도 있다.
- MySQL 실행하기
docker run -d -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true --name mysql mysql:5.7
- MySQL 데이터베이스를 실행
docker exec -it mysql mysql // 컨테이너 mysql에 접속하여 mysql 명령어 실행
create database wp CHARACTER SET utf8;
grant all privileges on wp.* to wp@'%' identified by 'wp';
flush privileges;
quit
- exec 명령어: exec 명령어는 run 명령어와 달리 실행중인 도커 컨테이너에 접속할 때 사용하며 컨테이너 안에 ssh server등을 설치하지 않고 exec 명령어로 접속한다.
도커 기본 명령어
docker ps
: 실행중인 컨테이너 목록을 확인하는 명령어docker ps -a
: 중지된 컨테이너도 확인하려면 -a 옵션docker stop [OPTIONS] CONTAINER [CONTAINER...]
: 실행중인 컨테이너를 중지하는 명령어. 실행중인 컨테이너를 하나 또는 여러개 (띄어쓰기) 중지할 수 있다.docker rm [OPTIONS] CONTAINER [CONTAINER...]
: 종료된 컨테이너를 완전히 제거하는 명령어docker logs [OPTIONS] CONTAINER
: 컨테이너가 정상적으로 동작하는지 확인하는 좋은 방법은 로그를 확인하는 것. -f, –tail 옵션docker images [OPTIONS] [REPOSITORY[:TAG]]
: 도커가 다운로드한 이미지 목록을 보는 명령어docker pull [OPTIONS] NAME[:TAG|@DIGEST]
: 이미지를 다운로드하는 명령어docker rmi [OPTIONS] IMAGE [IMAGE...]
: 이미지를 삭제하는 방법. images 명령어를 통해 얻는 이미지 목록에서 이미지 ID를 입력하면 삭제가 된다. 단, 컨테이너가 실행중인 이미지는 삭제되지 않는다.docker network create [OPTIONS] NETWORK
(docker network create app-network
): 도커 컨테이너끼리 이름으로 통신할 수 있는 가상 네트워크를 만든다. app-network 라는 이름으로 wordpress와 mysql이 통신할 네트워크를 만든다.docker network connect [OPTIONS] NETWORK CONTAINER
(docker network connect app-network mysql
): 기존에 생성된 컨테이너에 네트워크를 추가. mysql 컨테이너에 네트워크를 추가
docker run -d -p 8080:80 \
--network=app-network \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_NAME=wp \
-e WORDPRESS_DB_USER=wp \
-e WORDPRESS_DB_PASSWORD=wp \
wordpress
- 워드프레스를 app-network에 속하게 하고 mysql을 이름으로 접근
도커 기본 명령어(volume)
docker stop mysql
docker rm mysql
docker run -d -p 3306:3306 \
-e MYSQL_ALLOW_EMPTY_PASSWORD=true \
--network=app-network \
--name mysql \
-v /Users/subicura/Workspace/github.com/subicura/docker-guide/ch02/mysql:/var/lib/mysql \
mysql:5.7
- mysql을 삭제후에 다시 실행하면 데이터베이스 오류가 발생
-v
옵션으로 데이터베이스와 로컬 디렉토리를 연동, 이후 컨테이너 삭제 후 다시 컨테이너 생성을 하면 기존 데이터베이스와 동일한 데이터베이스 생성-v /my/own/datadir:/var/lib/mysql
도커 컴포즈
version: '2'
services:
db:
image: mysql:5.7
volumes:
- ./mysql:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
image: wordpress:latest
volumes:
- ./wp:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_PASSWORD: wordpress
docker-compose up -d
docker-compose down
: docker compose를 이용하여 mysql과 wordpress를 종료services
: 실행할 컨테이너 정의,docker run --name django
과 같다고 생각할 수 있음image
: 컨테이너에 사용할 이미지 이름과 태그, 태그를 생략하면 latest, 이미지가 없으면 자동으로 pullports
: 컨테이너와 연결할 포트(들), {호스트 포트}:{컨테이너 포트}environment
: 컨테이너에서 사용할 환경변수(들), {환경변수 이름}:{값}volumes
: 마운트하려는 디렉터리(들), {호스트 디렉터리}:{컨테이너 디렉터리}restart
: 재시작 정책, restart: “no”, restart: always, restart: on-failure, restart: unless-stoppedbuild
: 이미지를 자체 빌드 후 사용, image 속성 대신 사용함, 여기에 사용할 별도의 도커 파일이 필요함
도커 컴포즈 명령어
up
- docker-compose.yml에 정의된 컨테이너를 실행
docker-compose up
docker-compose up -d
docker-compose up --force-recreate
: 컨테이너를 새로 만들기docker-compose up --build
: 도커 이미지를 다시 빌드(build로 선언했을 때만)
stop
- 컨테이너 멈춤
docker-compose stop
docker-compose stop wordpress
: wordpress 컨테이너만 멈춤
start
- 멈춘 컨테이너를 재개
docker-compose start
docker-compose start wordpress
: wordpress 컨테이너만 재개
restart
- 컨테이너를 재시작
docker-compose restart
docker-compose restart wordpress
: wordpress 컨테이너만 재시작
down
- 컨테이너를 종료하고 삭제
docker-compose down
logs
- 컨테이너의 로그
docker-compose logs
docker-compose logs -f
ps
- 컨테이너 목록
docker-compose ps
exec
- 실행 중인 컨테이너에서 명령어 실행
- docker-compose exec {컨테이너 이름} {명령어}
docker-compose exec wordpress bash
build
- 컨테이너 build 부분에 정의된 내용대로 빌드
docker-compose build
docker-compose build wordpres
: wordpress 컨테이너만 build
도커 - 이미지 만들고 배포하기
도커 이미지 만들기 - 기본
- 이미지란
- 도커는 레이어드 파일 시스템 기반
- AUFS, BTRFS, Overlayfs, …
- 이미지는 프로세스가 실행되는 파일들의 집합(환경) 프로세스는 환경(파일)을 변경할 수 있음
- 이 환경을 저장해서 새로운 이미지를 만든다
- 읽기 전용 vs 쓰기 가능: 베이스 이미지에서 커스텀 후 새로운 이미지 만들기

$ docker run -it --name git ubuntu:latest bash
root@2f8bfff679f9:/# git
bash: git: command not found
root@2f8bfff679f9:/# apt-get update
root@2f8bfff679f9:/# apt-get install -y git
root@2f8bfff679f9:/# git --version
git version 2.17.1
$ docker commit git ubuntu:git
sha256:f95008381e220660f6330bcc544640091f59793e213ff5fe9a8298d784a345fa
$docker images | grep ubuntu
ubuntu git f95008381e22 17 seconds ago 186MB
ubuntu latest cf0f3ca922e0 5 days ago 64.2MB

- Dockerfile
명령어 | 설명 |
---|---|
FROM | 기본 이미지 |
RUN | 쉘 명령어 실행 |
CMD | 컨테이너 기본 실행 명령어 (Entrypoint의 인자로 사용) |
EXPOSE | 오픈되는 포트 정보 |
ENV | 환경변수 설정 |
ADD | 파일 또는 디렉토리 추가. URL/ZIP 사용가능 |
COPY | 파일 또는 디렉토리 추가 |
ENTRYPOINT | 컨테이너 기본 실행 명령어 |
VOLUME | 외부 마운트 포인트 생성 |
USER | RUN, CMD, ENTRYPOINT를 실행하는 사용자 |
WORKDIR | 작업 디렉토리 설정 |
ARGS | 빌드타임 환경변수 설정 |
LABEL | key - value 데이터 |
ONBUILD | 다른 빌드의 베이스로 사용될때 사용하는 명령어 |
- 이미지 빌드하기
docker build -t {이미지명:이미지태그} {빌드 컨텍스트}
$ docker build -t sample:1 .
- 현재 디렉토리의 Dockerfile로 빌드
- -f
옵션을 사용해 다른 위치의 Dockerfile 파일 사용 가능 - -t 명령어로 도커 이미지 이름을 지정
- {네임스페이스}/{이미지이름}:{태그} 형식
- -f
- 마지막에는 빌드 컨텍스트 위치를 지정
- 현재 디렉터리를 의미하는 점(.)을 주로 사용
- 필요한 경우 다른 디렉터리를 지정할 수도 있음
- .dockerignore
- .gitignore와 비슷한 역할
- 도커 빌드 컨텍스트에서 지정된 패턴의 파일을 무시
- .git이나 민감한 정보를 제외하는 용도로 주로 사용
- .git이나 에셋 디렉터리만 제외시켜도 빌드 속도 개선
- 이미지 빌드 시에 사용하는 파일은 제외시키면 안 됨
- Dockerfile
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y git
$ docker build -t ubuntu:git-dockerfile .
$ docker images | grep ubuntu
도커 이미지 만들기(웹 애플리케이션)
# 1. node 이미지 사용
FROM node:12-alpine
#2.패키지 우선 복사
COPY ./package* /usr/src/app/
WORKDIR /usr/src/app
RUN npm install
# 3. 소스 복사
COPY . /usr/src/app
# 4. WEB 서버 실행 (Listen 포트 정의)
EXPOSE 3000
CMD node app.js
docker build -t subicura/app .
docker run --rm -d -p 3000:3000 subicura/app
- FROM:
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
- 베이스 이미지 지정
- FROM ubuntu:latest
- FROM node:12
- FROM python:3
- COPY:
COPY [--chown=<user>:<group>] <src>... <dest>
- 파일 또는 디렉토리 추가
- COPY index.html /var/www/html/
- COPY ./app /usr/src/app
- RUN:
RUN <command>
- 명령어 실행
- RUN apt-get update
- RUN npm install
- WORKDIR:
WORKDIR /path/to/workdir
- 작업 디렉토리 변경
- WORKDIR /app
- EXPOSE
- 컨테이너에서 사용하는 포트 정보
- EXPOSE 8000
- CMD:
CMD ["executable","param1","param2"]
,CMD command param1 param2
- 컨테이너 생성시 실행할 명령어
- CMD [“node”, “app.js”]
- CMD node app.js
이미지 저장소
- docker login
- docker push {ID}/example
- docker pull {ID}/example
댓글남기기