이번 글에서는 도커에서 image가 무었인지 어떻게 관리해야 하는지에 관해서 정리해보겠습니다.
UTM hostos2 만들기
이번장을 들어 가기 전에 실습위해서 hostos1을 복제해서 hostos2를 만들겠습니다.
hostos1을 선택해서 큰론 버튼을 클릭해줍니다.
새로 생긴 인스턴스를 선택해서 edit버튼을 클릭해줍니다.
hostos2로 이름을 변경해 줍니다.
이 부분이 중요합니다. 네트워크탭에서 MAC Address의 random을 클릭해주세요. 복사를 한것이라서 hostos1과 MAC Address가 같아서 두개의 터미널을 뛰울경우 내부적으로 충돌이 나서 사용 하기 어려울 정도로 속도가 느려집니다. 랜덤하게 새로운 주소로 변경해줍시다. 그리고 저장을 눌러서 닫아줍시다.
hostos1은 잠시 멈춰 두고 hostos2만 켜서 진행해보겠습니다.
터미널을 열어줍시다.
네트워크 편에서 다룬 내용과 마찬가지로 서버 주소를 192.168.68.102로 변경하겠습니다. sudo vi /etc/netplan/00-installer-config.yaml으로 파일을 열어 줍니다.
주소를 변경해주고 저장합니다.
sudo netplan apply를 입력해서 변경사항을 적용해 줍니다.
ip a를 입력해서 적용된 것을 확인했습니다.
이제 실습 할 준비는 거의 다 되었습니다. 그런데 서버의 hostname이 hostos1으로 나오는 것이 실습시 혼동이 될 수 있기에 hostos2로 변경해보겠습니다.
sudo hostnamectl set-hostname hostos2 hostname sudo systemctl restart systemd-hostnamed sudo vi /etc/hosts
위처럼 hostos2로 이름을 변경하고 적용해준뒤 /etc/hosts를 열어줍니다.
127.0.1.1 hostos2로 입력 하신 후 서버를 재시작 하시면 변경되어 있습니다.
docker image 이해와 구조 확인
docker 컨테이너 서비스를 위한 이미지
이미지란 컨테이너를 만들기 위한 ReadOnly 파일입니다. 이미지 자체를 수정 할 수 는 없고 이미지로 컨테이너를 만들고 그 컨테이너를 수정해서 새로운 이미지를 만드는 방법으로 변경이 가능합니다.
위의 그림으로 이미지가 어떻게 관리되는지 흐름을 알 수 있습니다.
dockerfile은 베이스 이미지를 기반으로 애플리케이션에서 필요한 설정들을 정의하고 그걸 바탕으로 새로운 이미지를 만드는데 쓰이는 설정 파일입니다.
도커컴포즈는 마이크로 서비스를 만드는데 사용하는 부분인데 후에 강의에 나 올 때 같이 정의 하겠습니다. 주로 여러 개의 컨테이너를 같이 구성 할 때 사용합니다.
테스트가 완료된 이미지는 저장소에 저장하고 github등을 활용해서 dockerfile등을 관리합니다. 이 방법을 계속 반복하면 이미지를 유지 관리 하면 됩니다.
알겠죠?ㅎㅎ
방법은 실습에서 자세히 정리하면서 봐요.
이미지 내려받기
docker pull debian[:latest] docker pull library/debian:10 docker pull docker.io/library/debian:10 docker pull index/docker.io/library/debian:10 # 만일, private registry 나 클라우드의 저장소(ECR, GCR 등)의 이미지를 받는다면, docker pull 192.168.56.101:5000/debian:10 docker pull gcr.io/google-samples/hello-app:1.0
docker pull [image 이름] 이렇게 받으면 최신 버전으로 받아집니다. 뒤에 “:tag”를 추가하시면 그 버전에 해당하는 이미지가 다운로드 할수 있습니다.
docker pull debian:10
docker pull library/debian:10
docker pull docker.io/library/debian:10
docker pull index/docker.io/library/debian:10
위의 4개의 명령어는 같은 파일을 다운로드 합니다. docker hub에 퍼블릭으로 등록되어있는 이미지의 주소가 index/docker.io/library/debian:10이기 때문에 그 하위 경로를 적어도 적용됩니다.
또한 다른 서버 혹은 private 서버에서 이미지를 받을려면
docker pull 192.168.56.101:5000/debian:10
docker pull gcr.io/google-samples/hello-app:1.0
이렇게 주소를 적어주고 이미지:태그 입력하여 다운로드를 받을 수 있습니다.
실제 실습은 아래에서 정리하겠습니다.
gcr에서 이미지를 다운 받았습니다. 이처럼 도커 허브가 아니더라도 주소를 명시하면 다른 서버의 이미지를 받을 수 있습니다.
이미지 구조 확인
docker image inspect httpd:2.4 docker image inspect --format="{{.Os}}" httpd:2.4 docker image inspect --format="{{.RepoTags}}" httpd:2.4 docker image inspect --format="{{.ContainerConfig.ExposedPorts}}" httpd:2.4 docker image inspect --format="{{.RepoTags}} {{.Os}}" httpd:2.4
inspect 명령어는 이미지의 정보를 살펴 볼 수 있는 명령어입니다. –format옵션을 사용하면 이 정보에서 원하는 부분만 선택하여 출력 할 수 있습니다.
docker image history httpd:2.4
history명령어는 이미지를 만드는 dockerfile에 대한 정보를 보여줍니다.
docker hub repositories에 image push
이미지 올리기(push)
- Dockerfile 혹은 docker commit으로 생성된 이미지를 저장 하는 장소를 registry라고 한다.
- registry는 public, private이 있다.
여기서는 hub.docker.com에 올리는 방법과 private registry에 올리는 방법을 다르겠습니다.
docker login/logout
hub.docker.com에 이미지를 올릴려면 docker login을 해야합니다. 로그인하는 방법은 3가지 존재 하는데 그중에서 두 가지를 살펴보겠습니다.
id/password
아이디와 패스워드를 입력해서 로그인하는 방식입니다. 실수로 로그인을 해제 하지 않으면 비밀번호가 누출될 위험이 있어서 주의가 필요합니다.
docker login을 입력하면 username, password를 입력하는 란이 나옵니다. 거기에 계정 정보를 입력하면 로그인이 성공합니다.
하지만 경고문을 보면 /home/kevin/.docker/config.json에 암호화 되지 않은 비밀번호가 저장 될 거라고 나오네요. 실제로 가보면 비밀번호가 base64로만 암호화가 되어있습니다.
이건 쉽게 복호화가 가능해서 나중에 자리를 비울 때 로그아웃을 하지 않으면 비밀번호가 누출될 위험이 많습니다. 아래에 base64로 암복호화 하는법을 간단하게 살펴볼게요.
base64 -d옵션만 주면 복호화 되어서 이 방법은 조심해서 사용해야 합니다.
Access Tokens
hub.docker.com에서 토큰을 만들어 로그인을 하는 방식으로 실수로 로그인을 해제 하지 않더라도 토큰이 노출되지 비밀번호가 노출되지 않습니다. 토큰은 허브에서 비활성화 삭제가 언제든 가능해서 상대적으로 안전합니다.
Account Settings로 이동합니다.
New Access Token버튼을 클릭해 줍시다.
설명을 입력하고 아래에서 권한을 선택하면 됩니다. 여기서는 read, write, delete권한을 모두 주겠습니다. 생성 버튼을 눌러줍니다.
토큰이 생성되었습니다. Copy and Close버튼을 클릭하여 저장해 줍니다.
유저 홈에서(cd ~) vi .access_token으로 파일을 만들고 저장해 놓은 토큰을 붙여넣기 하고 저장합니다.
cat .access_token | docker login --username junseongday@gmail.com --password-stdin
입력하여 토큰으로 로그인합니다.
토큰을 수정을 눌러서 삭제 혹은 비활성화를 언제든지 할 수 있습니다. 여기서는 비활성화를 한 후 저장해보겠습니다.
비활성화를 한 상태에서 다시 토큰을 사용하여 로그인을 시도할 경우 위와 같은 오류가 발생하면서 로그인이 안되는 것을 알 수 있습니다.
Two-Factor Authentication
이건 해보진 않았지만 이름을 보면 OTP를 통해서 한번 더 인증을 거치는 방식으로 보입니다. 이게 가장 안전한 방식인거 같습니다.
로그아웃 하는 방법은 docker logout입니다.
docker [image] tag => push
docker image tag myweb:v1.0 junseongday/myweb:v1.0 docker push junseongday/myweb:v1.0
docker image tag 명령어로 태그를 만들어서 docker push로 저장 하면 됩니다.
docker hub에 이미지가 배포된 걸 확인 할 수 있습니다.
tag도 잘 적용되어서 올라갔습니다.
v1.1도 이미지 올리겠습니다.
태그가 v1.0, v1.1 이렇게 잘 작용 되었네요.
이건 hostos2에서 docker pull 받은 장면입니다. 이때는 아직 hostname을 변경하지 않아서 hostos1으로 나왔네요. 서버에서 이미지명:태그 이렇게 해서 받아지는 걸 확인 할 수 있습니다.
docker image 삭제
docker image rm [옵션] {이미지명[:태그] | 이미지ID} docker rmi [옵션] {이미지명[:태그] | 이미지ID} # 이미지 전체 삭제 docker rmi $(docker images –q) # 특정 이미지명이 포함된 것만 삭제. docker rmi $(docker images | grep debian) # 반대로 특정 이미지명이 포함된 것만 제외하고 모두 삭제. docker rmi $(docker images | grep -v centos) # 자주 사용하는 명령등을 전역 alias로 적용하여 활용하면 편리하다. vi .bashrc # 상태가 exited 인 container를 찾아서 모두 삭제 alias cexrm='docker rm $(docker ps --filter 'status=exited' -a -q)' # 설정한 alias를 적용하고 확인 source .bashrc 또는, ~$ . .bashrc
docker images를 입력해보면 실습 한지 얼마 되지 않았지만 많은 이미지들이 다운로드 된 걸 알 수 있습니다. 사용하지 않는 이미지들은 지워 주는게 용량면에서나 관리면에서 좋습니다.
삭제는 docker rmi 이미지명|이미지ID 할 수 있습니다. 그리고 이미지들을 사용하는 컨테이너가 존재하면 이미지는 삭제가 되지 않습니다. 그래서 컨테이너를 삭제하고 이미지를 삭제해야 합니다.
하지만 지워야 할게 많을 경우 하나 하나 입력하는 것은 힘들기에 .bashrc에 alias cexrm=’docker rm $(docker ps –filter ‘status=exited’ -a -q)’ 을 입력해서 cexrm입력하면 정지되어있는 컨테이너들을 한번에 삭제 할수 있습니다. 그런 다음에 불필요한 이미지들을 위의 명령어를 참고하여 지우시면 됩니다.
.bashrc에 alias를 입력하고 있다.
docker image 백업 및 이전
하나의 서버에서 이미지를 만들고 이이미지를 scp로 다른 서버로 전송해서 이미지를 사용해서 컨테이너를 올리는 방법을 살펴보자. 실제로 운영하다 보면 작업하는 애플리케이션을 공개 이미지를 올릴 수 가 없다. 그래서 이렇게 이미지를 만들어서 다른 서버로 간단하게 전송할 필요가 생길 때 사용 하면 된다. 여기서는 ch02에서의 dockerfile을 사용해서 간단하게 실습 해보겠습니다.
실습용 이미지를 만들기 위해서
cd ~ cd fastcampus/ch02 docker build -t testserver:v1.0 .
이미지가 잘 만들어졌는지 확인해 봅시다. testserver가 만들어졌습니다.
mkdir save_lab && cd $_ docker image save testserver:v1.0 > testserver1.tar docker image save testserver:v1.0 | gzip > testserver1.tar.gz docker image save testserver:v1.0 | bzip2> testserver1.tar.bz2 ls -lh
save_lab 폴더를 만들고 이동합시다. 도커에서는 이미지는 하나의 파일이 아니라 여러 개의 레이어로 이루어져 있습니다. 그래서 다른 서버로 전송을 하기 위해선 이 레이어들을 하나의 파일로 압축을 해야 합니다. tar, tar.gz, tar,bz2로 압축해서 용량 비교를 해보았습니다. 이론상 tar.bz2가 tar.gz보다 10%로 더 용량이 적어야 하는데 비슷해 보이네요.
scp testserver1.tar.gz kevin@192.168.68.102:/home/kevin/backup/testserver.tar.gz
scp를 사용해서 kevin@192.168.68.102서버에 /home/kevin/backup/testserver.tar.gz 위치에 전송하였습니다. backup 폴더는 미리 102 서버에 만들어 두어야 합니다.
backup에 전송한 파일이 잘 전달 되었네요.
docker image load < testserver.tar.gz docker images docker run --name testserver -itd -p 8200:80 testserver:v1.0
docker image load < testserver.tar.gz 명령어로 압축을 풀자. 압축은 gzip, bzip2등을 입력해야 하지만 해제는 입력 하지 않아도 된다.
docker run –name testserver -itd -p 8200:80 testserver:v1.0 실행하여 컨테이너를 생성하고 잘 생성되었는지 확인해보자.
docker registry 구성과 관리
private registry를 만드는 방법 중에 하나 이다. 주로 적은 용량의 이미지들을 공유할 때 사용하면 좋다고 한다. 사용 방법을 확인해 보자.
cd ~ mkdir registry_data docker pull registry docker images | grep registry docker run -d -v /home/kevin/registry_data:/var/lib/registry -p 5000:5000 --restart=always --name=local-registry registry docker ps | grep registry sudo netstat -nlp | grep 5000
registry를 다운 받고 컨테이너를 올려보자 -v /home/kevin/registry_data:/var/lib/registry으로 호스트의 폴더를 컨테이너의 폴더와 볼륨을 연결했다. 컨테이너 생성이 잘되었는지 확인해보자.
5개의 레이어로 받아졌고 docker.io에서 받았다.
docker image history로 포트가 5000으로 열린다는 것을 확인하였다.
docker run -d -v /home/kevin/registry_data:/var/lib/registry -p 5000:5000 –restart=always –name=local-registry registry
실행해서 컨테이너를 생성하고 확인해보자
curl -X GET http://192.168.68.101:5000/v2/_catalog docker image tag junseongday/myweb:v1.0 192.168.68.101:5000/myweb:v1.0 docker images docker push 192.168.68.101:5000/myweb:v1.0
curl -X GET http://192.168.68.101:5000/v2/_catalog
실행해보면 repositories가 비어있는 것을 알 수 있다.
방금 만든 registry를 경로로 태그를 하나 만들고 잘 만들어졌는지 확인해 봅시다.
이상태에서 docker push 192.168.68.101:5000/myweb:v1.0을 하면 전송이 잘 될 거 같지만 위와 같이 오류가 난다.
왜냐면 도커에 http://192.168.68.101:5000를 private registry로 등록을 안했기 때문입니다. 등록을 해봅시다.
sudo vi /etc/init.d/docker
31번째 줄에 DOCKER_OPTS=–insecure-registry 192.168.68.101:5000 이렇게 자신의 registry주소를 적고 저장합니다.
sudo vi /etc/docker/daemon.json { "insecure-registries": ["192.168.68.101:5000"] } sudo systemctl restart docker.service
daemon.json을 만들고 위의 { “insecure-registries”: [“192.168.68.101:5000”] }을 저장합니다.
sudo systemctl restart docker.service 실행하여 재시작 해줍니다.
이제 docker info로 확인해보면 아래에 insecure registries에 우리가 만든 registry가 등록 되어있는걸 확인 할수 있습니다.
이제 다시 푸시 해봅시다.
docker push 192.168.68.101:5000/myweb:v1.0
잘 전송이 되었습니다.
curl -X GET http://192.168.56.101:5000/v2/_catalog curl -X GET http://192.168.56.101:5000/v2/myweb/tags/list
잘 적용이 되었는지 확인해 봅시다
v1.1도 똑같이 푸시 하였습니다.
hostos2
docker pull 192.168.68.101/myweb:v1.0
여기서도 docker pull 192.168.68.101/myweb:v1.0을 하면 오류가 납니다. 위와 같이 insure registry로 등록을 하지 않았기 때문입니다. 등록을 해봅시다.
등록을 하지 않아서 오류가 나네요.
sudo vi /etc/init.d/docker
31번째 줄에 DOCKER_OPTS=–insecure-registry 192.168.68.101:5000 이렇게 자신의 registry주소를 적고 저장합니다.
sudo vi /etc/docker/daemon.json { "insecure-registries": ["192.168.68.101:5000"] } sudo systemctl restart docker.service
sudo vi /etc/docker/daemon.json 실행하여 { “insecure-registries”: [“192.168.68.101:5000”] } 저장한다. 그리고 sudo systemctl restart docker.service으로 재실행합니다.
docker info
Insecure Registries에 등록이 되었습니다.
다시 도커 풀을 해봅시다.
docker pull 192.168.68.101/myweb:v1.0
성공입니다.
오늘은 도커 이미지를 어떻게 관리하는지 그리고 사용 방법들을 전반적으로 살펴보았습니다. 갑자기 양이 많아진 거 같지만 느낌입니다.