본문 바로가기
Engineering WIKI/Docker

Docker 한방 요약 정리

by wonos 2020. 1. 17.

1. Docker란?

  • Docker는 리눅스 컨테이너 기술을 기반으로 하는 오픈 소스 가상화 플랫폼

2. Container(컨테이너) vs Virtual Machine(가상머신)

    • Virtual Machine :
        • 하드웨어 가상화 소프트웨어로 구현된 하드웨어
        • 소프트웨어로 구현된 하드웨어 그 위에 OS를 설치하고, 그 위에 소프트웨어를 설치함으로써 무겁고 느린 단점
        • 위 단점으로 반가상화 기술방식의 Xen이 등장하였지만, 성능문제는 해결되지 못함
        • 예 : VMWare, VirtualBox 등
    • Container:
        • 리눅스에서 하드웨어 가상화와 OS설치를 하지 않고 단순히 프로세스를 단독으로 격리시키는 기술 컨테이너라는 기술이 등장
        • 하드웨어 및 OS 계층을 두지 않고 프로세스만 격리하므로 실제 그냥 앱을 실행하는 경우와 거의 차이가 보이지 않을 정도로 Virtual Machine 에 비해 성능문제가 해결됨
        • 리눅스 OS에서 지원하는 기술로 LXC(Linux Container)라는 시스템 레벨의 컨테이너 기술을 제공
        • 초기 Docker는 LXC 기술을 채용했으나, 0.9버전 이후에는 libcontainer라는 자체 컨테이너 사용

3. Docker 실행환경별 차이점

  • Linux : 리눅스 컨테이너 기술을 기반으로 하기 때문에 Native 하게 지원됨
  • Mac & Windows : 내부에 경량의 Linux 가상머신을 띄운 후에 실행됨,(Mac에서는 xhyve, Windows에서는 Hyper-V가 내부에서 실행됨)
  • Windows : 리눅스 컨테이너와 Win32 네이티브 컨테이너를 함께 가지고 있으며 선택할 수 있음.
 
 

1. Play With Docker

  • Docker 웹 상에서 실행해볼 수 있는 사이트, 웹상에서 리눅스 쉘화면이 노출되며, Docker가 미리 설치되어 있는 가상머신을 제공해준다.

02-01

2. Docker for Mac/Windows 설치

~ docker version

Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:13:02 2018
 OS/Arch:      darwin/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: true

3. Linux Docker 설치

3.1 CentOS 7 이상 설치

  • 이전 버전 제거
$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine
  • 최신 저장소 설정
$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

$ sudo yum-config-manager \
      --add-repo \
      https://download.docker.com/linux/centos/docker-ce.repo
  • Docker 설치 (최신버전 설치)
$  yum install docker-ce 
  • Docker 설치 (특정 버전)
$ yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64            18.03.1.ce-1.el7.centos            docker-ce-stable 
docker-ce.x86_64            18.03.1.ce-1.el7.centos            @docker-ce-stable
docker-ce.x86_64            18.03.0.ce-1.el7.centos            docker-ce-stable 
...

$ yum install docker-ce-<버전번호>
$ yum install docker-ce-<버전번호> 
  • Docker 서비스 등록 및 시작
$ sudo systemctl enable docker
$ sudo systemctl start docker
  • (선택사항)docker 유저 그룹 생성 및 특정 유저를 docker 그룹에 귀속
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
  • docker run 확인
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

3.2 Ubuntu 설치

  • 이전 버전 제거
$ sudo apt-get remove docker docker-engine docker.io 
  • apt 패키지 색인 업데이트
$ sudo apt-get update 
  • HTTPS를 통해 저장소 사용할 수 있도록 설정
$ sudo apt-get install \
      apt-transport-https \
      ca-certificates \
      curl \
      software-properties-common
  • Docker 공식 GPG 키 추가
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 
  • 가장 안정적인 저장소 추가
$ sudo add-apt-repository \
     "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) \
     stable"
  • Docker 저장소 업데이트
$ sudo apt-get update 
  • Docker 설치
$ sudo apt-get install docker-ce

 

 

1. Docker 이미지 검색하기

$ docker search ubunutu

NAME                                    DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
arvindr226/ubunutu14.04-ssh             The Docker image for ssh in Ubuntu 14.04        1                                       [OK]
jpdc/ubunutu-apache-php-pgsql           Apache2, php5 and pgsql 9.3                     1                                       
jrlehtinen/ub14pfed                     Launches PingFed 9.0.2 in standalone mode on…   1                                       
csmanioto/pdi                           PDI With XRPD on Ubunutu 14                     0                                       
dawu415/ubunutu_java_buildpack_tools                                                    0                                       
gissehel/ubuntu-base                    Base for all my images created from an ubunu…   0                                       [OK]
waxzce/rust-1.7                         ubunutu based rust 1.7                          0                                       
v0rts/docker-ubuntu1604-ansible         Ubunutu 16.04 image used for application ans…   0                                       [OK]
...

2. 이미지 받아 오기

  • ubuntu 최신버전 받아오기
$ docker pull ubuntu:latest 

3. 이미지 목록 확인하기

  • 다운로드 받은 이미지 목록 출력하기
$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              113a43faa138        5 days ago          81.2MB
hello-world         latest              e38bc07ac18e        2 months ago        1.85kB

4. docker 이미지로 컨테이너 실행하기

  • docker 이미지를 컨테이너로 생성한 뒤 Bash를 실행합니다.
  • -it : 옵션을 통해 docker 이미지 컨테이너의 bash 쉘을 실행 시킵니다.
    • -i : interactive
    • ‘-t’ : 가상 tty(터미널같은입력창) 할당
  • bash를 사용할 수있도록 실행합니다.
  • docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

$ docker run -it ubuntu /bin/bash
root@fefe911e20e7:/#
  • 내부에서 ls 명령어를 입력해봅니다. 격리된 공간에서 ubuntu가 실행되었고 내부에서 실행이 가능해집니다.

5. docker 컨테이너 실행 확인

  • 커맨드 라인 창을 하나 더 실행하여 아래의 명령어를 입력합니다.
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
fefe911e20e7        ubuntu              "/bin/bash"         About a minute ago   Up About a minute                       sharp_varahamihira

6. 실행 중인 docker 정지 시키기

  • 실행 중인 docker 창은 두고 다른 창에서 아래의 명령 실행하기
  • sharp_varahamihira 는 docker ps에 나온 NAMES 항목이다.
  • docker가 컨테이너 실행 시 이름을 명시적으로 지정하지 않으면 임의의 이름을 생성한다.
  • docker stop <컨테이너 이름 또는 ID>
$ docker stop sharp_varahamihira 
  • 실행 중 이던 화면은 아래와 같이 나온다.
  • docker 가 실행화면에서 exit 명령어를 입력하면 똑같은 효과가 생긴다.
root@fefe911e20e7:/# exit $ 

7. 정지된 컨테이너 다시 실행하기

  • docker start <컨테이너 이름 또는 ID>
$ docker start sharp_varahamihira 
  • 실행 확인
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
fefe911e20e7        ubuntu              "/bin/bash"         12 minutes ago      Up 18 seconds                           sharp_varahamihira

8. 실행 중 컨테이너에 접속하기

  • docker attach <컨테이너 이름 또는 ID>
$ docker attach sharp_varahamihira
  root@fefe911e20e7:/#

9. 외부에서 컨테이너 안의 명령어 실행하기

  • docker exec <컨테이너 이름 또는 ID> 명령어
$ docker exec sharp_varahamihira echo "Hello Docker"
Hello Docker

10. 컨테이너 삭제 하기

  • docker rm <컨테이너 이름 또는 ID
  • 기본적으로 아래의 명령어는 실행이 정지된 상태에서만 유효하다.
$ docker rm sharp_varahamihira 
  • 실행 중인 컨테이너의 경우 강제로 지우겠다는 옵션 -f 를 추가 해야한다.
$ docker rm -f sharp_varahamihira 

11. 이미지 삭제 하기

  • docker rmi <이미지 이름>:<태그>
$ docker rmi ubuntu:latest 
  • 삭제 확인
$ docker images 

12. MySQL 서비스 올리기

  • -d 는 데몬으로 실행 옵션
  • -p 는 포트 연결 옵션 서버포트:컨테이너포트
  • -e 는 환경 변수
  • 외부에서 3307 포트로 접속이 가능하다.
$ docker run -d -p 3307:3306 --name mysql -e MYSQL_DATABASE=homestead -e MYSQL_USER=homestead -e MYSQL_PASSWORD=homestead -e MYSQL_ROOT_PASSWORD=qwer1234 mysql:5.7

 

 

Docker Image 만들기 1

 

1. Dockerfile 이란?

  • 컨테이너 내부 환경을 정의함
  • Docker 이미지 외부 리소스와의 맵핑 정보를 정의함
  • 빌드가 성공적으로 이루어진 이미지의 경우 Docker가 설치된 어디에서나 똑같이 실행될 것을 기대할 수 있음.

 

2. Dockerfile 간단 작성

  • 특정 경로에 디렉토리를 생성 한후 .dockerignore 파일을 생성한다.
    • .dockerignore : docker 이미지 빌드 시 무시 될 파일들을 기재한다. .gitignore와 비슷하다.
 node_modules
 npm-debug.log
 Dockerfile*
 docker-compose*
 .dockerignore
 .git
 .gitignore
 README.md
 LICENSE
 .vscode
  1. Dockerfile 작성
    • python관련 이미지를 기반으로,
     # 파이썬 이미지를 기반으로 함
     FROM python:2.7-slim
        
     # Docker 이미지 내부에서 RUN, CMD, ENTRYPOINT의 명령이 실행될 디렉터리를 설정
     WORKDIR /app
        
     # 현재 디렉터리에 있는 파일들을 이미지 내부 /app 디렉터리에 추가함
     ADD . /app
        
     # requirements.txt 파일을 기반으로 파이썬 패키지들을 실행함
     RUN pip install --trusted-host pypi.python.org -r requirements.txt
        
     # 80포트를 외부로 노출함
     EXPOSE 80
        
     # 환경변수를 설정함
     ENV NAME World
        
     # 쉘을 사용하지 않고 컨테이너가 시작되었을 때 아래 명령을 실행함 'python app.py' 가 실행됨
     CMD ["python", "app.py"]
  2. requirements.txt 작성
  3. Flask Redis 
  4. app.py 파일 작성
    • 파이썬 웹프레임워크인 flask를 이용한 코드 작성
     from flask import Flask
     from redis import Redis, RedisError
     import os
     import socket
        
     # Connect to Redis
     redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
        
     app = Flask(__name__)
        
     @app.route("/")
     def hello():
         try:
             visits = redis.incr("counter")
         except RedisError:
             visits = "<i>cannot connect to Redis, counter disabled</i>"
        
         html = "<h3>Hello {name}!</h3>" \
                "<b>Hostname:</b> {hostname}<br/>" \
                "<b>Visits:</b> {visits}"
         return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
        
     if __name__ == "__main__":
         app.run(host='0.0.0.0', port=80)
  5. Dockerfile을 기반으로 이미지 빌드하기
    • friendlyhello 라는 이름으로 현재 디렉토리를 빌드함.
    • 마지막에 . 주의 요망 현재디렉토리라는 것을 명시 해야함.
    • docker build -t <이미지이름>:<태그> <경로>
    • 태그를 생략할 경우 자동으로 latest 가 붙는다.
    • -t 옵션 : 이미지 명칭과 태그를 지정하는 옵션
     $ docker build -t friendlyhello:first . 
  6. 이미지 확인
    1. $ docker images
          
       REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
       friendlyhello       first               af346c6c2f35        About a minute ago   132MB
       python              2.7-slim            d0d1b97dd328        6 days ago           120MB
  7. 이미지 실행 ($ docker run -p 4000:80 friendlyhello:first)
  8. 로컬에서 웹서버 구동 확인 

 

1. .dockerignore

  • docker 이미지 빌드시 무시할 파일들을 입력합니다.
  • .gitignore 와 유사합니다.

 

2. FROM

  • 어떤 이미지를 기반으로 생성할지 기록합니다. 부모이미지가 됩니다.
  • 이미지 이름만 입력할 수도, 태그와 함께 입력할 수도 있습니다.
  • FROM은 항상 설정해야하고, 맨 첫 줄에 설정해야합니다.
  • FROM에 설정한 이미지가 로컬에 있으면 로컬을 우선 적용하고, 없으면 Docker Hub에서 받아 옵니다.
  • FROM은 여러개 설정할 수 있습니다.
FROM ubuntu
FROM ubuntu:14.07

 

3. MAINTAINER

  • MAINTAINER는 Dockerfile 작성자를 입력합니다. 생략 가능
MAINTAINER Suwoni <suwoni@suwoni.com>

4. WORKDIR

  • WORKDIR은 RUN과 CMD등의 Dockerfile에 사용되는 이미지 내부에서 실행할 명령어의 실행 디렉터리를 설정합니다.
WORKDIR /app/src 

5. ADD

  • ADD는 파일을 이미지에 추가
  • 압축파일인 경우 해제 후 추가(tar.gz의 경우 gz만 해제하고 추가합니다.)
  • 인터넷 경로를 입력할 수 있습니다.
ADD test.sh /entrypoint.sh
ADD . /src-dir
ADD test.zip /test
ADD http://blog.news.com/a.txt /b.txt

6. COPY

  • ADD 와 비슷하게 파일을 이미지에 추가
  • 압축파일을 해제 하지 않음
  • URL 사용할 수 없음

7. RUN

  • FROM에서 설정한 이미지 위에서 스크립트 혹은 명령을 실행
  • 쉘로 실행하기(이미지에 /bin/sh 실행파일이 있는 경우)
RUN apt-get install -y  nginx
RUN git clone https://github.com/docker/docker.git
  • 쉘없이 바로 실행하기(이미지에 /bin/sh 실행파일이 없는 경우)
RUN ["apt-get", "install", "-y", "nginx"]
RUN ["git", "clone", "https://github.com/docker/docker.git"]

8. CMD

  • 이미지가 컨테이너로 실행이 시작될 때 실행(docker run 또는 docker start 시)
  • Dockerfile에서 한번만 사용할 수 있음
  • 쉘로 실행하기(이미지에 /bin/sh 실행파일이 있는 경우)
CMD git clone https://github.com/docker/docker.git 
  • 쉘없이 바로 실행하기(이미지에 /bin/sh 실행파일이 없는 경우)
CMD ["git", "clone", "https://github.com/docker/docker.git"] 

9. ENTRYPOINT

  • CMD 와 마찬가지로 이미지가 컨테이너로 실행이 시작될 때 실행(docker run 또는 docker start 시)
  • Dockerfile에서 한번만 사용할 수 있음
  • 실행 형식은 CMD와 동일

10. ENTRYPOINT와 CMD가 동시에 사용되는 경우

  • CMD는 ENTRYPOINT에 매개 변수만 전달하는 역할을 합니다.
ENTRYPOINT ["echo"]
CMD ["hello docker"]

11. CMD와 ENTRYPOINT 차이

  • CMD는 docker run 실행 시 바로 명령어를 입력하는 경우 Dockerfile에 CMD는 무시됩니다.
FROM ubuntu
CMD ["echo", "Hello, Docker"]
$ docker run ubuntuimage echo world
world
  • ENTRYPOINT의 경우 실행시 --entrypoint 옵션을 줄 경우 무시됩니다.
$ docker run --entrypoint="cat" 이미지명 

12. EXPOSE

  • 노출시킬 port를 설정 docker run 명령어의 --expose옵션과 동일
  • 한꺼번에 작성 또는 여러줄 작성 가능
EXPOSE 80 443 21 
EXPOSE 80
EXPOSE 443
EXPOSE 21

13. ENV

  • 환경변수 설정
  • 환경변수는 RUN, CMD, ENTRYPOINT에서도 적용가능
ENV ENV_VARIABLE aaaa
CMD echo $ENV_VARIABLE
  • ENV 에서 설정한 값을 docker run 시에 변경할 수 있습니다.
$ docker run -e ENV_VARIABLE=bbbb 이미지명
bbbb
  1. VOLUME
  • 디렉터리 내용을 컨테이너에 저장하지 않고 호스트에 저장하도록 설정
VOLUME /data
VOLUME ["data", "/var/log/hello"]
  • 위 처럼 설정할 경우 호스트(이미지를 실행한 os환경)에서 /var/lib/docker/volumes 아래의 임의의 난수로 저장된 디렉토리 안에 데이터가 들어가므로 좋은 방법이 아니다.
  • docker run -v <호스트디렉토리>:<컨테이너디렉토리> 형식으로 이미지 내부디렉토리를 호스트 디렉토리로 연결할 수 있다.
  1. ONBUILD
  • 생성한 이미지를 기반으로 다른 이미지가 생성될 때 명령을 실행