도커 무작정 따라하기
도커 무작정 따라하기: 도커가 처음인 사람도 60분이면 웹 서버를 올릴 수 있습니다!
출처: https://www.slideshare.net/pyrasis/docker-fordummies-44424016
도커의 특징
도커의 성능
- 도커는 하드웨어 가상화 계층이 없음
- 메모리 접근, 파일 시스템, 네트워크 전송 속도가 가상 머신에 비해 월등히 빠름
도커의 특징
이미지 버전 관리도 제공하고 중앙 저장소에 이미지를 올리고 받을 수 있음 (push/pull)
GitHub와 비슷한 형태로 도커 이미지를 공유하는 Docker Hub 제공 (GitHub처럼 유료 저장소도 제공)
다양한 API를 제공하여 원하는 만큼 자동화 가능, 개발과 서버 운영에 매우 유용!
가상 머신의 문제점
그런데 이미지와 컨테이너는 뭐가 다른 거지?
도커 이미지와 컨테이너
도커 이미지
이미지는 서비스 운영에 필요한 서버 프로그램, 소스 코드, 컴파일된 실행 파일을 묶은 형태
저장소에 올리고 받는건 이미지 (push/pull)
컨테이너는 이미지를 실행한 상태!
이미지로 여러 개의 컨테이너를 만들 수 있음
운영체제로 치면 이미지는 실행파일
이고 컨테이너는 프로세스
도커의 이미지 처리 방식
도커는 이미지의 바뀐 부분을 어떻게 관리하나?
유니온 파일 시스템 형식 (aufs, btrfs, devicemapper)
- 도커는 베이스 이미지에서 바뀐 부분만 이미지로 생성
- 컨테이너로 실행할 때는 베이스 이미지와 바뀐 부분을 합쳐서 실행
- Docker Hub 및 개인 저장소에서 이미지를 공유할 때 바뀐 부분만 주고 받음
- 각 이미지는
의존 관계
형성
서비스 운영 환경과 도커
지금까지의 서버 환경
- 지금까지는 물리 서버를 직접 운영 했음
- 호스팅 또는 IDC 코로케이션 서비스 사용
- 서버 구입과 설치에 돈이 많이 들고 시간이 오래 걸림
클라우드 환경
- 가상화가 발전하면서
클라우드 환경으로 변환
- 가상 서버를
임대
하여 사용한 만큼만요금 지불
- 클릭 몇 번 만으로 가상 서버를 생성
- 이젠 자동으로 서버를 추가하고 삭제하기까지…
- 서버 대수가 많아지면서 사람이 일일이 세팅하기 힘들어짐
- 이제 서버 세팅과 배포는 어떻게?
Immutable Infrastructure
Immutable Infrastructure
라는 패러다임이 나옴- 호스트 OS와 서비스 운영 환경(서버 프로그램, 소스코드, 컴파일된 바이너리)을
분리
- 한 번 설정한 운영 환경은
변경하지 않는다(Immutable)
는 개념
- 서비스 운영 환경을
이미지로 생성
한 뒤서버에 배포하여 실행
- 서비스가 업데이트되면 운영 환경 자체를 변경하지 않고,
이미지를 새로 생성하여 배포
- 클라우드 플랫폼에서 서버를 쓰고 버리는 것과 같이 Immutable Infrastructure도
서비스 운영 환경 임지를 한 번 쓰고 버림
- 도커는 Immutable Infrastructure를 구현한 프로젝트
편리한 관리
- 서비스 환경
이미지만 관리
하면 됨 - 중앙 관리를 통한
체계적인 배포와 관리
- 이미지 생성에
버전 관리 시스템 활용
확장
- 이미지 하나로
서버를 계속 찍어낼 수 있음
- 클라우드 플랫포의 자동 확장(Auto Scaling) 기능과 연동하여
손쉽게 서비스 확장
테스트
- 개발자 PC, 테스트 서버에서 이미지를 실행만 하면 서비스 운영 환경과
동일한 환경이 구성됨
- 테스트가 간편
가볍다
- 운영체제와 서비스 환경을
분리
하여 가볍고(Lightweight) 어디서든 실행 가능한(Portable) 환경 제공
도커 요약
- 고래는 서버에서 여러 개의 컨테이너(이미지)를
실행
하고 이미지저장과 배포(운반)
를 의미 - 도커(Docker)는 부두 노동자를 뜻함 컨테이너를 다루는 도커의 기능과 비슷함
- 도커는 서비스 운영 환경을 묶어서 손쉽게 배포하고 실행하는
경량 컨테이너
기술
도커 설치하기
공식문서 ⇒ https://docs.docker.com/install/linux/docker-ce/ubuntu/
도커 레파지토리를 추가
# gedit /etc/apt/sources.list deb https://apt.dockerproject.org/repo ubuntu-xenial main
HTTPS 통신에 사용되는 패키지와 공개키를 설치
# apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
linux-image extra와 docker-engine 패키지를 설치
sudo apt-get update # apt-get install linux-image-extra-$(uname -r) # apt-get install docker-engine
root@server:~# docker version Client: Version: 17.05.0-ce API version: 1.29 Go version: go1.7.5 Git commit: 89658be Built: Thu May 4 22:10:54 2017 OS/Arch: linux/amd64 Server: Version: 17.05.0-ce API version: 1.29 (minimum version 1.12) Go version: go1.7.5 Git commit: 89658be Built: Thu May 4 22:10:54 2017 OS/Arch: linux/amd64 Experimental: false
main.go 파일 작성
package main import ( "fmt" "log" "net/http" ) func main(){ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){ log.Println("received request") fmt.Fprintf(w, "Hello Docker !!!") }) log.Println("start server") server := &http.Server{Addr: ":8000"} if err := server.ListenAndServe(); err != nil { log.Println(err) } }
설치
# apt install golang-go # go run main.go
DockerFile 생성
root@server:~/docker# gedit Dockerfile
FROM golang:1.9 RUN mkdir /echo COPY main.go /echo CMD [ "go", "run", "/echo/main.go" ]
docker
- snippet.shell
docker image --help docker image build --help root@server:~/docker# docker image build -t example/echo:latest .
-t
는 이미지 이름:태그
이미지 목록 확인
- snippet.shell
root@server:~/docker# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE example/echo latest e5bf61deed81 2 minutes ago 750MB golang 1.9 ef89ef5c42a9 10 months ago 750MB
- snippet.shell
root@server:~/docker# docker image ls -a REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> b4ba25ac2cae 3 minutes ago 750MB example/echo latest e5bf61deed81 3 minutes ago 750MB <none> <none> 58f3cb19c839 3 minutes ago 750MB golang 1.9 ef89ef5c42a9 10 months ago 750MB
이미지 내용 변경
내용 변경 후 이미지 다시 만들기
- snippet.shell
root@server:~/docker# docker image build -t example/echo:latest . Sending build context to Docker daemon 3.072kB Step 1/4 : FROM golang:1.9 ---> ef89ef5c42a9 Step 2/4 : RUN mkdir /echo ---> Using cache ---> 58f3cb19c839 Step 3/4 : COPY main.go /echo ---> b812938cbabc Removing intermediate container c91757d70919 Step 4/4 : CMD go run /echo/main.go ---> Running in 5e76624a9714 ---> 133a6f8f5426 Removing intermediate container 5e76624a9714 Successfully built 133a6f8f5426 Successfully tagged example/echo:latest root@server:~/docker# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE example/echo latest 133a6f8f5426 46 seconds ago 750MB <none> <none> e5bf61deed81 8 minutes ago 750MB golang 1.9 ef89ef5c42a9 10 months ago 750MB
도커 이미지 실행
- snippet.shell
root@server:~/docker# docker container run -p 9000:8000 -d example/echo:latest 25bdbb71d2591730d259c7dcb07da0557add80a9ba70e96753c907b462d4b704
- snippet.shell
root@server:~/docker# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 25bdbb71d259 example/echo:latest "go run /echo/main.go" 2 hours ago Up 2 hours 0.0.0.0:9000->8000/tcp thirsty_goldstine
- 이름을 줄 수 있다.
컨테이너 하나 더 실행
- snippet.shell
root@server:~/docker# docker container run -p 9001:8000 -d example/echo:latest 5a140cf82ca1112164487268e2b2d161a84a725aa5d5af5247a2e711725c9032 root@server:~/docker# docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5a140cf82ca1 example/echo:latest "go run /echo/main.go" 6 seconds ago Up 4 seconds 0.0.0.0:9001->8000/tcp priceless_shockley 25bdbb71d259 example/echo:latest "go run /echo/main.go" 2 hours ago Up 2 hours 0.0.0.0:9000->8000/tcp thirsty_goldstine
컨테이너 삭제
- snippet.shell
root@server:~/docker# docker container rm 5a Error response from daemon: You cannot remove a running container 5a140cf82ca1112164487268e2b2d161a84a725aa5d5af5247a2e711725c9032. Stop the container before attempting removal or force remove root@server:~/docker# docker container rm -f 5a 5a root@server:~/docker# docker container rm -f 25 25 root@server:~/docker# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-f
옵션으로 강제 종료
컨테이너 id 조회
- snippet.shell
root@server:~/docker# docker container ps -q 4ad6c2a7994c d08c882043e6
- snippet.shell
docker container rm -f $(docker container ps -q)
attach 를 위한 옵션
- snippet.shell
root@server:~/docker# docker container run -it -p 9000:8000 -d example/echo:latest /bin/bash 9ec1ad3c49f00164195eb7872ab0600f58a5cf58079e566a84bb1e83f253f714 root@server:~/docker# docker attach 9e root@9ec1ad3c49f0:/go#
종료
- snippet.shell
root@9ec1ad3c49f0:/echo# exit exit root@server:~/docker# docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES root@server:~/docker# docker container ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9ec1ad3c49f0 example/echo:latest "/bin/bash" 7 minutes ago Exited (127) 3 minutes ago infallible_joliot
다시 실행
- snippet.shell
root@server:~/docker# docker container restart 9e 9e root@server:~/docker# docker container ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9ec1ad3c49f0 example/echo:latest "/bin/bash" 9 minutes ago Up 3 seconds 0.0.0.0:9000->8000/tcp infallible_joliot
stop
- snippet.shell
root@server:~/docker# docker container stop 9e 9e root@server:~/docker# docker container ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9ec1ad3c49f0 example/echo:latest "/bin/bash" 11 minutes ago Exited (0) 2 seconds ago infallible_joliot
컨테이너 실행
- snippet.shell
root@server:~/docker# docker container run -it -p 9000:8000 --name echo1 -d example/echo:latest e2c45c8b92f9c2196b9fbc2bcca10b777384e6ab3f332778116a350ce41bb97e root@server:~/docker# docker container run -it -p 9001:8000 --name echo2 -d example/echo:latest 0371d5eb3d1ed93dfb7408266775781dcdac37e5113b3074d9d43262f2200d6f root@server:~/docker# docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0371d5eb3d1e example/echo:latest "go run /echo/main.go" 8 seconds ago Up 7 seconds 0.0.0.0:9001->8000/tcp echo2 e2c45c8b92f9 example/echo:latest "go run /echo/main.go" 48 seconds ago Up 47 seconds 0.0.0.0:9000->8000/tcp echo1
nginx
- snippet.shell
root@server:~/docker# docker container run -d -p 9003:80 --name web2 nginx fd906f33ad9133796809583f31b275685971dcc82d81a437ecda97a46ea4511b
- snippet.shell
root@server:~/docker# docker container ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fd906f33ad91 nginx "nginx -g 'daemon ..." 2 minutes ago Up 2 minutes 0.0.0.0:9003->80/tcp web2 e6eb11fb9666 nginx "nginx -g 'daemon ..." 6 minutes ago Exited (0) 4 minutes ago web1 0371d5eb3d1e example/echo:latest "go run /echo/main.go" 7 minutes ago Up 7 minutes 0.0.0.0:9001->8000/tcp echo2 e2c45c8b92f9 example/echo:latest "go run /echo/main.go" 8 minutes ago Up 8 minutes 0.0.0.0:9000->8000/tcp echo1 9ec1ad3c49f0 example/echo:latest "/bin/bash" 42 minutes ago Exited (0) 30 minutes ago infallible_joliot
컨테이너 검색
- snippet.shell
root@server:~/docker# docker container ps --filter "ancestor=example/echo" CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0371d5eb3d1e example/echo:latest "go run /echo/main.go" 9 minutes ago Up 9 minutes 0.0.0.0:9001->8000/tcp echo2 e2c45c8b92f9 example/echo:latest "go run /echo/main.go" 10 minutes ago Up 10 minutes 0.0.0.0:9000->8000/tcp echo1
- snippet.shell
root@server:~/docker# docker container ps -a --filter "ancestor=example/echo" CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0371d5eb3d1e example/echo:latest "go run /echo/main.go" 10 minutes ago Up 10 minutes 0.0.0.0:9001->8000/tcp echo2 e2c45c8b92f9 example/echo:latest "go run /echo/main.go" 11 minutes ago Up 11 minutes 0.0.0.0:9000->8000/tcp echo1 9ec1ad3c49f0 example/echo:latest "/bin/bash" 44 minutes ago Exited (0) 32 minutes ago infallible_joliot
기본 명령어
docker image
- build : Dockerfile → Image 생성
- pull : library/nginx:latest
- push : [myid]/
- docker login 후에 push
docker container run [image_name]
- -d : detach
- -it : interaction
- -p : port forwarding
- –name : 이름 지정
docker container stop [container_id]
docker container restart
docker container rm
- -f : 강제 삭제
이미지 올리기
- snippet.shell
root@server:~/docker# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE example/echo latest 133a6f8f5426 3 hours ago 750MB <none> <none> e5bf61deed81 3 hours ago 750MB nginx latest 53f3fd8007f7 3 weeks ago 109MB golang 1.9 ef89ef5c42a9 10 months ago 750MB
- snippet.shell
root@server:~/docker# docker image tag example/echo:latest jacegem/echo:latestroot@server:~/docker# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE example/echo latest 133a6f8f5426 3 hours ago 750MB jacegem/echo latest 133a6f8f5426 3 hours ago 750MB <none> <none> e5bf61deed81 3 hours ago 750MB nginx latest 53f3fd8007f7 3 weeks ago 109MB golang 1.9 ef89ef5c42a9 10 months ago 750MB
- snippet.shell
root@server:~/docker# docker image push jacegem/echo:latest The push refers to a repository [docker.io/jacegem/echo] 1542d130dabd: Pushed da8b71e70fad: Pushed 186d94bd2c62: Mounted from library/golang 24a9d20e5bee: Mounted from library/golang e7dc337030ba: Mounted from library/golang 920961b94eb3: Mounted from library/golang fa0c3f992cbd: Mounted from library/golang ce6466f43b11: Mounted from library/golang 719d45669b35: Mounted from library/golang 3b10514a95be: Mounted from library/golang latest: digest: sha256:d30f59e7e31708f73d8fcf21f301b6bc46ac0ad8669703e2d305e4bd3c9043cf size: 2417
- snippet.shell
root@server:~/docker# docker image pull myanjini/echo Using default tag: latest latest: Pulling from myanjini/echo 55cbf04beb70: Already exists 1607093a898c: Already exists 9a8ea045c926: Already exists d4eee24d4dac: Already exists 9c35c9787a2f: Already exists 8b376bbb244f: Already exists 0d4eafcc732a: Already exists 186b06a99029: Already exists c6f2dfa6c4bc: Pull complete 0ef374528dd6: Pull complete Digest: sha256:349156f17a9f55e548bff2dc2301be0e4937506b25464a1e9a401f1f39728fe5 Status: Downloaded newer image for myanjini/echo:latest
- snippet.shell
root@server:/var/www/html# docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 59aff7e41078 example/echo "go run /echo/main.go" 15 seconds ago Created angry_bhaskara fd906f33ad91 nginx "nginx -g 'daemon ..." 2 hours ago Up 2 hours 0.0.0.0:9003->80/tcp web2 e6eb11fb9666 nginx "nginx -g 'daemon ..." 2 hours ago Exited (0) 2 hours ago web1 0371d5eb3d1e example/echo:latest "go run /echo/main.go" 2 hours ago Up 2 hours 0.0.0.0:9001->8000/tcp echo2 e2c45c8b92f9 example/echo:latest "go run /echo/main.go" 2 hours ago Up 2 hours 0.0.0.0:9000->8000/tcp echo1 9ec1ad3c49f0 example/echo:latest "/bin/bash" 2 hours ago Exited (0) 2 hours ago infallible_joliot root@server:/var/www/html# docker container stop e2 e2 root@server:/var/www/html# docker container run -d -p 9000:8000 example/echo 400484c6af559d31ec5235f02dc56f0f2a840d903748bd34f14573dbb0accd76
- snippet.shell
root@server:~/docker# docker container exec 40 ls /echo main.go root@server:~/docker# docker container rm -f $(docker container ls -a -q) 400484c6af55 59aff7e41078 fd906f33ad91 e6eb11fb9666 0371d5eb3d1e e2c45c8b92f9 9ec1ad3c49f0
- snippet.shell
root@server:~/docker# docker system prune WARNING! This will remove: - all stopped containers - all volumes not used by at least one container - all networks not used by at least one container - all dangling images Are you sure you want to continue? [y/N] y Total reclaimed space: 0B
- snippet.shell
root@server:~/docker# docker container run -d -p 9000:80 nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 743f2d6c1f65: Pull complete 6bfc4ec4420a: Pull complete 688a776db95f: Pull complete Digest: sha256:23b4dcdf0d34d4a129755fc6f52e1c6e23bb34ea011b315d87e193033bcd1b68 Status: Downloaded newer image for nginx:latest 862795b066d8425bf832e9fce88e0566789b6c196517b945cf2b6b19913a2b2b root@server:~/docker# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 862795b066d8 nginx "nginx -g 'daemon ..." 23 seconds ago Up 21 seconds 0.0.0.0:9000->80/tcp hardcore_brattain
- snippet.shell
root@server:~/docker# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 862795b066d8 nginx "nginx -g 'daemon ..." 23 seconds ago Up 21 seconds 0.0.0.0:9000->80/tcp hardcore_brattain root@server:~/docker# docker container exec 86 ls /usr/share/nginx/html 50x.html index.html
- snippet.shell
root@server:~/docker# docker container cp 86:/usr/share/nginx/html/index.html . root@server:~/docker# ls Dockerfile index.html main.go
- snippet.shell
root@server:~/docker# docker container cp ./index.html 86:/usr/share/nginx/html/index.html
자동 설치 스크립트
도커는 리눅스 배포판 종류를 자동으로 인식하여 도커 패키지를 설치해주는 스크립트를 제공
- snippet.shell
$ sudo wget -qO- https://get.docker.com | sh
- get.docker.com 스크립트로 도커를 설치하면 hello-world 이미지도 자동 설치됨
- hello-world 이미지는 사용하지 않을 것이므로 모두 삭제
- snippet.shell
$ sudo docker rm `sudo docker ps -aq` $ sudo docker rmi hello-world
우분투
- 자동 설치 스크립트를 사용하지 않고 우분투에서 직접 설치하기
- 버전은 14.04 LTS 64비트 기준
- snippet.shell
$ sudo apt-get update $ sudo apt-get install docker.io $ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
/usr/bin/docker.io 실행 파일을 /usr/local/bin/docker 로 링크하여 사용
Redhat Enterprise Linux, centos
- 자동 설치 스크립트를 사용하지 않고 레드햇 엔터프라이즈 리눅스(RHEL) 와 centos에서 패키지로 직접 설치 하기
- RHEL과 CentOS 6 패키지 저장소에 docker-io가 없으므로 EPEL(Fedora Extra Packages For Enterprise Linux) 저장소를 사용할 수 있도록 설정
- snippet.shell
$ sudo yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6.8.noarch.rpm $ sudo yum install docker-io
- AWS EC2에 설치되는 Amazon Linux(RHEL 기반)는 EPEL 저장소를 바로 사용할 수 있으므로 epel-release-6.8.noarch.rpm을 설치하지 않아도 됨
- centos 7 에서는 docker 패키지를 설치
CentOS 7
- snippet.shell
$ sudo yum install docker
Docker 서비스 실행하기
- snippet.shell
$ sudo service docker start
부팅했을 때 자동으로 실행하기
- snippet.shell
$ sudo chkconfig docker on
최신 바이너리 사용하기
- 배포판 버전이 오래되었거나, centOS 같이 버전업이 보수적인 배포판에서는 도커 패키지 버전이 낮은 경우가 있음
- 배포판 별 패키지가 아닌 빌드 된 바이너리를 직접 사용하는 방법
이미 패키지로 설치했을 때
- snippet.shell
$ sudo service docker stop $ sudo wget http://get.docker.com/builds/Linux?x86_64/docker-latest -O $(type -P docker) $ sudo service docker start
새로 설치할 때
- snippet.shell
$ wget https://get.docker.com/builds/Linux/x86_4/docker-latest $ chmod +x docker-latest $ sudo mv docker-latest /usr/local/bin/docker $ sudo /usr/local/bin/docker -d
URL을 docker-latest로 지정하면 가장 최신 버전을 받고, docker-1.3.0처럼 지정하면 특정 버전을 받음
도커 사용해보기
도커 명령
Search 명령으로 이미지 검색하기
- snippet.shell
# docker search <이미지 이름> $ sudo docker search ubuntu
- 보통 ubuntu, centos, redis 등 OS 나 프로그램 이름을 가진 이미지가 공식 이미지
- 나머지는 사용자들이 만들어서 공개한 이미지
- 도커는 Docker Hub(https://registry.hub.docker.com)를 통해 이미지를 공유하는 생태계가 구축되어 있음