Docker

markyang92·2021년 4월 23일
0

docker

목록 보기
1/3
post-thumbnail
post-custom-banner

  • 컨테이너화

  • 만든 컨테이너를 어디에서나 구동 가능
  • 가상머신처럼 컨테이너독립적으로 실행
  • 가상머신보다 빠르고, 쉽고, 효율!

도커의 특징

  • 확장성/이식성
    • 도커가 설치되어 있다면 언제/어디서든 컨테이너를 실행할 수 있다.
    • 특정 회사나 서비스에 종속적이지 않다.
    • 쉽게 개발 서버를 만들 수 있고 테스트 서버 생성도 간편하다.
  • 표준성
    • 도커를 사용하지 않는 경우 ruby, nodejs, go, php로 만든 서비스들의 배포 방식은 제각각 다름
    • 컨테이너라는 표준으로 서버를 배포하므로 모든 서비스들의 배포과정이 동일해짐
  • 이미지
    • 이미지에서 컨테이너를 생성하기 때문에 반드시 이미지를 만드는 과정 필요
    • Dockerfile을 이용하여 이미지를 만들고 처음부터 재현 가능
    • 빌드 서버에서 이미지를 만들면 해당 이미지이미지 저장소에 저장하고 운영서버에서 이미지를 불러옴
  • 설정 관리
    • 설정은 보통 환경변수로 제어
    • MYSQL_PASS=password와 같이 컨테이너를 띄울 때, 환경변수를 같이 지정
    • 하나의 이미지가 환경변수에 따라 동적으로 설정 파일을 생성하도록 만들어져야함
  • 자원관리
    • 컨테이너는 삭제 후 새로 만들면 모든 데이터가 초기화됨
    • 업로드 파일을 외부 스토리지와 링크하여 사용하거나 S3 같은 별도의 저장소가 필요
    • 세션이나 캐시를 memcached나 redis와 같은 외부로 분리

  • 클라이언트 <-> 서버 관계
    • docker CLI는 도커 호스트에 명령을 전달하고 결과를 받아서 출력

설치

$ curl -s https://get.docker.com/ | sudo sh
  • 명령을 입력하고 패스워드를 입력하면 리눅스 배포판에 따라 자동으로 최신버전의 도커 설치
  • MacOS, Windows를 사용 중이라면 Docker for Mac / Docker for Windows를 사용하는게 낫다.
    • 도커는 기본적으로 linux를 지원하기 때문에 MacOS와 Windows에 설치되는 Docker는 가상머신에서 설치된다.
      • MacOS는 xhyve, Windows는 Hyper-V를 사용

  1. [hostname]은 당연히 sudo group에 추가되어 있어서 sudo 권한이 있을 것임
$ cat /etc/group | grep sudo
sudo:x:27:dhyang
  1. [hostname]docker 그룹에 넣자.
$ sudo usermod -aG docker [hostname]
# sudo usermod -aG docker dhyang


  1. reboot하거나 sudo -su USERNAME하면 reboot 없이 바로 적용됨

설치 확인

$ sudo docker version
Client: Docker Engine - Community			# 클라이언트
 Version:           20.10.6					# Local host의 도커
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        370c289
 Built:             Fri Apr  9 22:47:17 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community			# 서버
 Engine:							# 실제 Docker
  Version:          20.10.6
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:45:28 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.4
  GitCommit:        05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Cannot connect to the Docker daemon at unix:///var/run/docker.sock

  • docker daemon이 running 중이지 않다.
  1. systemd
$ sudo systemctl start docker
$ sudo systemctl enable docker
  1. system V
$ sudo service docker status
 * Docker is not running      # <- 도커 대몬 is not running
$ sudo service docker start   # <- 도커 대몬 start!
  * Starting Docker: docker                                               [ OK ] 

docker lifecycle




pull 'ubuntu image'

  • 예시로, Ubuntu 이미지를 받아보자.
    docker search ubuntu 커맨드를 실행하면, 받을 수 있는 이미지가 나온다.

$ docker pull ubuntu[:20.04]
# 20.04 버전을 받으려면, :20.04 태그를 붙여서 pull 받는다.

run - 컨테이너 실행

  • run: image컨테이너생성
  • exec: 실행 중인 컨테이너에게 접속 / 명령어 전달
$ docker run [OPTIONS] IMAGE[:TAG | @DIGEST] [COMMAND] [ARG...]

run의 option

Option                     Description
-ddetaced mode(백그라운드 모드)나중에 컨테이너를 attach 하고 싶으면
$ docker attach <NAME>
-p호스트와 컨테이너의 포트를 연결-p 1234:80
내컴 1234: 호스트 80 연결
항상!! 내컴 : docker_host이다.
-v호스트와 컨테이너의 디렉토리 연결-v /var/jenkins_home:/var/jenkins_home
내컴 /var/jeknins_home을 호스트 /var/jenkins_home으로 연결
-e컨테이너 내에서 사용할 환경변수 설정
--name컨테이너 이름 설정
--rm프로세스 종료시 컨테이너 자동 제거
-it-i와 -t를 동시에 사용한 것
터미널 입력을 위한 옵션
--network네트워크 연결
-u <user>지정한 user 로 로그인-u root : 도커 컨테이너 실행 시, root로 접속
-u jenkins : 도커 컨테이너 실행 시, jenkins로 접속
--privilegedprivileged 권한을 주고 컨테이너를 실행한다.
기본적으로 컨테이너는 이 옵션을 주지 않으면 Unprivileged모드이다.
--restart <OPTION>컨테이너 재시작에 관한 설정.
자세한 설명은 아래 참고

privileged

  • 도커 컨테이너는 기본적으로 Unprivileged 모드로 실행되며, 이 모드에서는 시스템 주요 자원에 접근할 수 있는 권한이 부족하기 때문에, 특정 장치 등의 시스템 자원에 접근할 수 없다.
  • By default, Docker containers are “unprivileged” and cannot, for example, run a Docker daemon inside a Docker container. This is because by default a container is not allowed to access any devices, but a “privileged” container is given access to all devices (see the documentation on cgroups devices)
  • 예를 들어, 도커 컨테이너를 기본으로(Unprivileged 모드로) 실행하면 네트워크 인터페이스의 활성화/비활성화나 IP 주소의 변경 등이 불가능하다.

container 재실행에 대한 옵션

  • 가령 container
    • -it 옵션을 주지 않고 실행
    • 기본적으로 interactiveprocess가 돌아가지 않는다.
    • ctrl+c로 컨테이너를 종료
    • reboot
  • 하면, stop 상태가 된다.
    • 이 때, 다시 docker start <name>으로 재 시작한다.
  • 이에 대해, container를 올릴 때, 옵션을 주어 설정할 수 있는데,
    --restart <OPTION>으로 줄 수 있다.
<OPTION>설명
--restart unless-stopped부팅자동으로 컨테이너재시작
--restart no프로세스가 종료되더라도 컨테이너를 재시작하시 않는다.
--restart on-failure프로레스 exit code 가 0 이 아닐 때 재시작한다.
지정하지 않으면 계속해서 컨테이너를 재시작 한다.
--restart always프로세스의 exit code 와는 관계없이 재시작

service를 사용해, container 재실행

  • systemd 내용 참고
  • /etc/systemd/system 에 <service_name>.service서비스 파일 를 만든다.
    • /etc/systemd/system/docker-container.service
[Unit]
Wants=docker.service
After=docker.service

[Service]
RemainAfterExit=yes
ExecStart=/usr/bin/docker restart <container이름> # 시작
# 컨테이너 재 시작 후 시행할 명령
ExecStartPost=/usr/bin/docker exec --user <user> <container이름> bash -c "실행후 컨테이너에게 실행할 명령어; 웹서버를 켠다던가.."

# 서비스를 멈출때 실행할 명령
ExecStop=/usr/bin/docker stop <container이름>

[Install]
WantedBy=multi-user.target
$ sudo systemctl start <service_name>	# 서비스 시작
$ sudo systemctl enable <service_name>	# 부팅시 실행할 수 있도록 서비스 활성화
/etc/systemd/system/multi-user.target.wants/<service_name>.service -> \
  /etc/systemd/system/<service_name>.service 
  # multi-user-target에 심볼릭 링크가 생성된다.

Docker image 상태

dettach / attach

  • dettach
Creating optionDescription
docker run -itctrl + p , ctrl + q
docker run -ictrl + p, ctrl + q 로 빠져 나올 수 없다. stdin을 파괴시킨다.
docker runctrl + p, ctrl + q로 빠져나올 수 없다.
SIGKILL 로 컨테이너를 종료할 수 있다.

  • attach
    • $ docker attach <container name>

commit / stop / rm

1. 도커 우분투 컨테이너 만들고 실행
$ docker run --name git -it --rm ubuntu:latest bash
                이름  ̄ ̄ ̄         ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
                                 IMAGE : TAG
 
--- 도커 내부 ---
# 도커 내부에서 ctrl+p ctrl+q 누르면 종료하지 않고 도커를 나올 수 있다.

--- local ---

2. 로컬로 돌아와 커밋

$ docker ps
CONTAINER ID   IMAGE         COMMAND      CREATED         STATUS         PORTS    NAMES
abab0aa93b82   ubuntu:latest "/bin/bash"  6 minutes ago   Up 6 minutes            git
						                실행 중인 컨테이너 이름  ̄ ̄
$ docker commit git dhyang/ubuntu:git
             이름 ̄ ̄   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄: ̄ ̄ ̄ ̄
어떤 name을 커밋할거임?     IMAGE    : TAG <- IMAGE:TAG 이건 새로 붙이는거임

=> 현재 사용 중인 도커 컨테이너 로컬 커밋시킴
-----------------------------------------------------------------------
=> 나중에 다시 사용 하고 싶을 때!

$ docker images
REPOSITORY	TAG	IMAGE ID 	CREATED		SIZE
dhyang/ubuntu	git	039cd2eb92d7	4 minutes ago 	97.7MB
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄    ̄ ̄
 IMAGE		TAG				<-- 이름은 저장되어 있지 않음
 
$ docker run --name zsh -it --rm dhyang/ubuntu:git
           새로운 이름 ̄ ̄ ̄          ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
  run은 새로운 이름 만들어 실행할 수 있음     IMAGE   : TAG (태그까지 다 붙여야함)

-v: 디렉토리 연결

  • Docker Volume을 사용하는 경우
    • Host <=> Container Volume 공유
      • Container의 Data는, Container 삭제 시, write layer도 사라지기 때문에, Host에 남겨둘 필요가 있음
    • Container <=> Container Volume 공유

-v <args>description
-v <container_path><container_path>에 명시된, container 내부의 path를
host에서 볼 수 있게한다.
-v <HOST>:<CONTAINER>Hostcontainer 사이 매핑 시킬 수 있음

1. -v <CONTAINER_PATH>

  1. -v <CONTAINER_PATH>를 주면, Container 내부의 <CONTAINER/PATH>로 준 경로가 공유된다.
  2. 기본적으로 Container가 실행되면, Volume/var/lib/docker/volumes/도커에서 생성한 hash값인 디렉토리가 생성됨
    2.1. $ docker run -it -v /data <image>로 도커 컨테이너 run!
    2.2 /var/lib/docker/volumes/[hash_value]/_data와 연결됨![]

2.3 -v /data 옵션을 줘서, Host_data라는 이름으로 생성 된 것이 아니라, 원래 _data라는 디렉토리로 생성됨


2. -v <HOST>:<CONTAINER>

  • 1번 방식은 Host에서 찾아가기 너무 힘듦
    그래서 도커 run 시, -v <HOST>:<CONTAINER>매핑 시킬 수 있음
  • $ docker run -v <HOST_PATH>:<CONTAINER_PATH> <IMAGE>![]
  • 컨테이너가 stop되어도 Host에서 사용가능!
  • run 시, <CONTAINER_PATH>에서 없으면, 생성해서 컨테이너 올림

주의점

  1. 도커 호스트 컨테이너는 Up 상태에선 적용안된다!!
  2. Host에서 주는 Path의 권한의 uid:gidContainer User와 맞출 것
    2.1. 내컴(local)에서 도커와 연결할 디렉터리 일단 만듦
$ mkdir -p /var/jenkins_home


$ chown -R 1000:1000 /var/jenkins_home/
  • /var/jenkins_home/ 디렉터리의 uid와 gid를 1000으로 변경
    UID:GID 참고

2.2 docker run

$ docker run -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -d --name jenkins jenkins/jenkins:lts

# -d: detached mode
$ echo 'http://'($curl -s ifconfig.co)''
http://27.122.242.71	# public IP

http://27.122.242.71:8080 으로 jenkins에 Access 가능

Public IP, Private IP 참고


3. /var/run/docker.sock 연결

  • docker을 설치시 Docker daemonDocker CLI가 설치/ 실행된다.
    • 그래서 콘솔 화면에서 도커 명령 -> Docker CLI -> /var/run/docker.sock 소켓이 Docker daemon에게 명령어 전달
    • /var/run/docker.sock파일만 공유하면 Local에 설치된 Docker를 컨테이너 내부에서 사용할 수 있고, 또한 컨테이너 내부에 설치된 Docker를 다른 컨테이너 내부에서 사용 가능

  • 도커 컨테이서 실행 시, local /var/run/docker.sock과 컨테이너 내부의 /var/run/docker.sock을 연결한다.
$ docker run -it --rm --name pllpokko -v /var/run/docker.sock:/var/run/docker.sock ubuntu:20.04
  • -v 옵션을 이용해 /var/run/docker.sock을 공유한다.

-p: 포트를 연결

  • -p <HOST_PORT>:<DOCKER_PORT>

HOST_PORT: Host의 Port
DOCKER_PORT: Docker의 Port


django 웹 프레임워크 연결

  1. Host에 docker container를 실행 시키고, 그 위에 django web framework를 runserver로 동작 시킨다.

  1. 도커 실행 명령어는 아래와 같다.
$ docker run [-it] [-d] [--rm] --name <name> -p 8585:8585 <IMAGE>:<TAG>
$ 이후 컨테이너 내에서 web server를 실행시키던가, docker exec로 하던가..

웹 어플리케이션 실행

$ docker run --rm -p 5678:5678 hashicorp/http-echo -text="hello world"
  • -d: detached mode
  • -p: 컨테이너의 포트 <-> 호스트의 포트
    • -p 5678:5678: 내 PC의 5678 port <-> host 5678 port 연결
  • hashcorp?: hashcorp라는 회사에서 만든 웹서버
  • 브라우저를 열고 localhost:5678에 접속하면 메시지를 볼 수 있다.
    • localhost:[내가 들어갈 나의 PORT]

Redis 실행하기

$ docker run --rm -p 1234:6379 redis
  • Redis라는 메모리 기반 DB 실행

MySQL 실행하기

$ docker run -d -p 3306:3306 \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=true \
  --name mysql \
  mysql:5.7


MySQL 데이터베이스 추가

$ docker exec -it mysql mysql
create database wp CHARACTER SET utf8;
grant all privileges on wp.* to wp@'%' identified by 'wp';
flush privileges;
quit


wordpress 블로그 실행

! 앞에서 MySQL 컨테이너와 데이터베이스를 추가한 상태!

  • localhost:8080 으로 접속

commands

exec

  • exec 명령어는 run과 달리 실행 중 도커 컨테이너에 접속, 명령어 전달할 때 사용
$ docker exec -it <container_name> 

ps

  • 실행 중인 컨테이너 목록 확인!
$ docker ps


  • 중지된 컨테이너 목록 확인
$ docker ps -a


  • 도커 실행 중인 컨테이너 용량 확인
$ docker ps -s


stop

$ docker stop [OPTIONS] <CONTAINER NAME | ID> [[NAME | ID] ...]
  • 실행 중인 컨테이너를 중지 (Exited로)


rm

$ docker rm [OPTIONS] <CONTAINER NAME | ID> [[NAME | ID] ...]
  • 종료된 컨테이너를 완전히 제거

logs

$ docker logs [OPTION] <CONTAINER NAME | ID>
  • 컨테이너가 정상적으로 동작하는지 확인하는 좋은 방법은 로그를 확인하는 것
optiondescription
-f로그를 보여주고 끝나지 않고, 대기하면서 추가적인 로그가 나오면 계속 띄워줌
--tail-

images

$ docker images [OPTIONS] [REPOSITORY[:TAG]]
  • 도커가 다운로드한 이미지 목록

images --all: 모든 이미지 보여줌

$ docker images --all
  • 이런 필요없는(?) 이미지들은 지워주자.

rmi

$ docker rmi [OPTIONS] IMAGE [IMAGE...]
  • 이미지 삭제

network

network create

$ docker network create [OPTIONS] NETWORK

# e.g.
$ docker network create app-network
  • 도커 컨테이너끼리 이름으로 통신할 수 있는 가상 네트워크 만듬
    • app-network라는 가상 네트워크 만듬

network connet

  • app-network 라는 이름으로 wordpress와 mysql이 통신할 네트워크 만든다.
$ docker network create app-network		# app-network라는 가상 네트워크 만듬
$ docker network connect app-network mysql	# app-network <--> mysql 컨테이너를 연결



docker run -d -p 8080:80 \ 
  --network=app-network \	# --network=<NET_WORK> : 지금 생성하는 컨테이너를 <NET_WORK> 에 연결
  -e WORDPRESS_DB_HOST=mysql \
  -e WORDPRESS_DB_NAME=wp \
  -e WORDPRESS_DB_USER=wp \
  -e WORDPRESS_DB_PASSWORD=wp \ 
  wordpress


-v: volume mount

$ docker run -v /host/dir:/container/dir
# host의 /host/dir과 도커 컨테이너내 /container/dir과 연결된다.
  • nfs도 연결된다.

  1. mysql을 삭제 후 다시 실행해보자.
$ sudo docker mysql
$ sudo docker rm mysql
$ sudo docker run -d -p 3306:3306 \
-e MYSQL_ALLOW_EMPTY_PASSWORD=true \
--network=app-network \
--name mysql \
mysql:5.7

# Error occured!
# Fail to access DB 
# 컨테이너가 종료되면서 다 사라짐

  1. -v 옵션을 추가하여!! mysql을 실행해보자.
$ sudo docker run -d -p 3306:3306 \
-e MYSQL_ALLOW_EMPTY_PASSWORD=true \
--network=app-network \
-v /Users/subicura/Workspace/github.com/subicura/docker-guide/ch02/mysql:/var/lib/mysql \
mysql:5.7

Dockerfile

  • Dockerfile 로 image를 빠르게 만들어 낼 수 있다.
    • docker pull 받아서 들어가서 또 하나하나 패키지를 설치할 시간이 없잖어?

docker-compose

Docker Compose는 다중 컨테이너 애플리케이션을 정의하고 공유할 수 있도록 개발된 도구입니다. Compose에서 서비스를 정의하는 YAML 파일을 만들고, 단일 명령을 사용하여 모두 실행하거나 모두 종료할 수 있습니다.
Compose를 사용할 경우의 ‘중요한’ 이점은 파일에서 애플리케이션 스택을 정의하고 프로젝트 리포지토리 루트에 파일을 저장하여(이제 버전 제어 사용) 다른 사용자가 프로젝트에 참여하기 쉽게 만들 수 있다는 것입니다. 사용자가 리포지토리를 복제하고 Compose 앱을 시작하기만 하면 됩니다. 사실상, GitHub/GitLab에서 정확히 이 작업을 수행하는 많은 프로젝트를 볼 수 있습니다.

https://docs.microsoft.com/ko-kr/visualstudio/docker/tutorials/use-docker-compose


설치

  • 설치
    • release 버전은 항시 업데이트 될 수 있음!!
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" \
--output ~/docker-compose
$ sudo chmod +x ~/docker-compose
$ sudo mv ~/docker-compose /usr/local/bin/docker-compose

  • 설치확인
$ docker-compose version
docker-compose version 1.26.0, build d4451659
docker-py version: 4.2.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

docker-compose.yml 실행

  • docker-compose.yml이 있는 디렉토리에서, 아래의 명령어 실행
$ docker-compose up

docker-compose.yml

기본 예제

아무_이름:
     image: USER_ID/IMAGE:TAG
     container_name: container_name # docker run --name <name> 과 똑같음
     volumes:
         - /my/data:/container/data
     stdin_open: true
     tty: true
  • 실행
$ docker-compose up
Creating container_name ... done
Attaching to continer_name
# 도커 서비스 중!


mysql + wordpress

mysql + wordpress 를 yml 파일로 만들 수 있다.

version: '2'
services: 
    db:
        image: mysql:5.7
        volumes:
            - ./mysql:/var/lib/mysql
        restart: always
        environment: 
            MYSQL_ROOT_PASSWORD: wordpress
            MYSQL_DATABASE: wordpress
            MYSQL_USE: 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_USER: wordpress
            WORDPRESS_DB_PASSWORD: wordpress
  • docker-compose.yml

$ ls
docker-compose.yml
$ docker-compose up


.dockerignore


hub

  • docker hub
    • Import! 무료 계정은 하나의 Image만 priviate 가능하다!!


deploy


push

  • 도커hub에 이미지를 올리려면 이미지 이름: <Docker Hub User ID>/<IMAGE NAME>:<TAG>형식

  1. 도커 로그인
$ docker login
Username:
Password:
Email:
Login Succeeded!

  1. push
$ docker push pllpokko/ubuntu:sourcelist_kor
               ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄: ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
                       IMAGE : TAG

pull

$ docker pull [OPTIONS] NAME[:TAG|@DIGEST]

# e.g.
$ docker pull ubuntu:18.04
  • pull 명령

내부 HTTP를 사용할 경우, daemon.json

  • 내부 HTTP를 통해 docker image를 사용할 경우,
    /etc/docker/daemon.jsoninsecure 한 내부 HTTP 주소를 적어야한다.
  • 파일: /etc/docker/daemon.json
    • 없으면 만들자.
{
  "insecure-registries": ["IP:PORT"]
}

  • 예: 192.168.1.100:5000 을 사용 시,
{
  "insecure-registries": ["192.168.1.100:5000"]
}

vscode와 연계

  1. docker image pull
$ docker pull <image>:<tag>

  1. docker image run
$ docker run --name <name> -u <user> [-it] <image>:<tag>

  1. docker Extension

Docker system

도커 저장 장소

  • 도커의 내 컴퓨터에서 저장소는 /var/lib/docker 이다.
  • 이건 어떤 도커 이미지 상에서 돌려봐도 동일하게 나온다.
    • docker 1번
    • docker 2번
profile
pllpokko@alumni.kaist.ac.kr
post-custom-banner

0개의 댓글