Docker(1) : 도커 공부 정리
프로젝트 배포 및 이식성 향상을 위해서 도커를 공부하게 되었다. Devops 공부를 지금까지 너무 소홀히 하였기 때문에... 야마다 아키노리 저의 도커/쿠버네이티스를 활용한 컨테이너 개발 실전 입문을 읽고 정리를 해보려 한다.
💚 도커의 기본 개념
- 도커 이미지 : 도커 컨테이너를 구성하는 파일 시스템과 실행할 어플리케이션 설정을 하나로 합친 것으로 컨테이너를 생성하는 템플릿 역할을 한다. 도커 이미지 하나로 여러 개의 컨테이너를 생성해서 실행하는 것이 가능함
- 도커 컨테이너 : 도커 이미지를 기반으로 생성되며 파일 시스템과 어플리케이션이 구체화되어 실행되는상태이다.
🚀 도커 이미지 작성을 위한 인스트럭션
- 인스트럭션을 통해 빌드부터 사용될 명령어를 지정해준다.
✍ FROM 인스트럭션
- 베이스 이미지 지정
- Dockerfile로 이미지를 빌드할 때 제일 첫 번째로 FROM 인스트럭션에 지정된 이미지를 내려 받음
- 이 이미지들은 도커 허브라는 레지스트리에 공개된 것으로 내가 지금 작성 중인 언어의 런타임이 설치된 이미지이다.
✍ RUN 인스트럭션
- 이미지를 실행 시 컨테이너 안에서 실행할 명령을 정의하는 인스트럭션
- RUN의 명령어 인자는 도커 컨테이너 안에서 실행할 명령을 그대로 작성한 것이다.
✍ COPY 인스트럭션
- 도커가 동작 중인 호스트 머신의 파일이나 디렉토리를 도커 컨테이너 안으로 복사함
✍ CMD 인스트럭션
- 도커 컨테이너를 실행할 때 컨테이너 안에서 실행할 프로세스를 지정한다. RUN 인스트럭션은 애플리케이션 업데이트 배치, 즉 이미지 빌드할 때 사용이 되고, CMD는 어플리케이션 자체 실행 즉 컨테이너를 시작할 때 한 번만 실행하면 된다.
인자 표기 방식 | 동작 기능 |
CMD ["실행파일", "인자1" , "인자2"] | 실행 파일에 인자 2개를 전달함 |
CMD 명령 인자1 인자2 | 명령과 인자를 전달한다. 셸에서 실행되므로 셸에 정의된 변수를 참조하는 것이 가능하다. |
CMD ["인자1", "인자2"] | ENTRYPOINT에 지정된 명령에 사용할 인자를 전달한다. |
🚀 도커 이미지 빌드
✍ 명령어
docker image build -t 이미지명[:태그명] Dockerfile의 경로
- t 옵션 : 이미지명 지정이며 태그명도 지정이 가능하며 생략할 때는 태그명이 생략될 때는 latest 태그가 붙는다.
-t 옵션과 이미지명은 반드시 지정해야 한다고 생각하는 것이 좋음!
✍ 예시
docker image build -t example/echo:latest
빌드를 실행하게 되면 베이스 이미지를 내려 받고 RUN, COPY 인스트럭션에 지정된 명령이 단계적으로 실행된다.
- f 옵션 : 그냥 Docker file build 명령어만을 사용하게 되면 기본 지정된 이름인 Dockerfile을 찾게 된다. 그 외의 파일명으로 지정된 Dockerfile을 사용하고 싶다면 이 옵션을 작성해야 한다.
docker image build -f Dockerfile-test -t example/echo:latest
--pull 옵션 : 이미지를 빌드하기 위해서면 Dockerfile의 FROM 인스트럭션에 지정한 이미지를 레지스트리에서 내려받은 뒤 이를 베이스 이미지로 하여 새로운 이미지를 빌드해야 됨 --pull 옵션을 사용하면 매번 베이스 이미지를 강제로 새로 받아온다.
docker image build --pull=true -t example/echo:latest
여기서 --pull=true는 최신베이스 이미지를 사용할 수 있도록 하는 옵션이다.
🚀 이미지 검색
- 도커 허브에 저장된 리파지토리를 검색할 수 있음
- 도커 허브에 등록된 리포지토리에도 깃허브처럼 스타가 매겨짐 (많이쓰일수록 스타수 증가)
- 리파지토리까지만 검색이 가능하고, 태그는 검색 불가
docker search [options] 검색키워드
- 태그까지 보고 싶다면 리파지토리로 직접 들어가서 보던가 아니면 아래의 명령어를 작성하여 api를 사용해서 태그를 확인한다.
curl -s 'https://hub.docker.com/v2/repositories/library/golang/tags/?page_size=10' \ |jq-r '.results[].name'
🚀 이미지 내려받기
- docer image pull 명령
docker image pull [options] 리파지토리명[:태그명]
예시
d/ocker image pull jenkins:latest
🚀 속성 확인하는 명령어
docker image ls
- Repository : 같은 이름을 가졌지만 서로 다른 태그가 달린 이미지 집합으로 깃허브 저장소처럼 소유자명/어플리케이션명과 같은 이름이 지정됨
- TAG : 특정 이미지를 식별하기 위한 값
- IMAGE ID : 이미지를 유일하게 식별하기 위한 식별자
- CREATED : 이미지 생성 후 경과 시간
- SIZE : 이미지 파일 크기
를 정보로 알아낼 수 있음
✍ 도커 이미지 명령어
- 이미지 하위 명령어 출력
docker image --help
✍ 도커 이미지에 태그 붙이기
- 도커 이미지의 특정 버전을 구별하기 위하여 태그를 붙인다.
- 애플리케이션을 수정하고나서 이미지를 빌드하면 매번 다른 이미지가 된다. 즉 원래 맨 처음에는 같은 이미지였지만, 수정 후 다른 IMAGE_ID 값이 할당되기 때문에 Dockerfile을 편집했을 뿐만아니라 COPY 대상이 되는 파일의 내용이 바뀌어도 IMAGE ID 값이 바뀌게 된다.
- 즉, 버전은 이미지의 ID값이라고 이해하면 된다.
- 이미지 아이디를 따로 설정하지 않으면 latest임
-이미지 태그 생성하기
docker image tag 기반이미지명[:태그] 새이미지명[:태그]
예시
docker image tag example/echo:latest example/echo:0.1.0
- latest 이미지에 0.1.0 태그를 부여한 것
✍ 도커 이미지를 외부에 공개하기
docker image push [options] 리파지토리명[:태그]
💚 과정
1. 계정 생성한 뒤 docker login 명령으로 도커 허브에 로그인한다.
2. docker image tag 명령어를 사용하여 example/echo 라는 이름의 이미지의 네임스페이스를 바꿔, 도커 허브 ID과 같이 변경한다.
3. docker image push 명령에 인자로 등록할 이미지를 지정한다.
+ 개인이미지를 만드는 것이므로, 공개된 이미지를 그냥 사용할 경우에는 만들 필요는 없음
💚 도커 컨테이너
✍ 도커 컨테이너의 생애주기
도커 컨테이너 실행
명령어
docker container run [options] 이미지명[:태그] [명령] [명령인자...]
docker container run [options] 이미지ID [명령] [명령인자...]
예시
docker container run example/echo:latest
--name 옵션 : 컨테이너에 이름 붙여서 실행할 수 있도록 함
docker container run --name [컨테이너명] [이미지명]:[태그]
docker container run -t -d --name gihyo-echo example/echo:latest
-d 옵션 : 표준 출력에 더해 해쉬값(container id)까지 보일 수 있도록 해준다.
docker container run -d example/echo:latest
-i : 컨테이너를 실행할 때 컨테이너 쪽 표준 입력과의 연결을 그대로 유지한다.
-t : i와 t 옵션과 함께 사용하는 경우가 많다. 즉, 유사 터미널 기능을 활성화하는 옵션이다. 즉, i와 t를 사용한다. -it옵션을 사용한다.
--rm : 컨테이너를 종료할 때 컨테이너를 파기하도록 하는 옵션임
-v : 호스트와 컨테이너 간에 디렉토리나 파일을 공유하기 위해 사용하는 옵션이다.
🧐 포트포워딩이란?
- 로컬 포트를 컨테이너가 리스닝하는 것
- 즉, 컨테이너의 포트를 컨테이너의 외부에서 사용할 수 있도록 하는 것이다.
- 다음 GET 요청 명령어를 저 위의 명령어까지 실행된 상태로 실행하게 되면, Connection Refused라는 연결 실패 에러가 뜨게 된다.
curl http://localhost:8080/
왜?
- 도커는 독립된 하나의 가상머신임. 우리가 위에서 만든 echo 어플리케이션은 8080 포트를 리스닝하고 있긴 한데, 이 포트는 컨테이너 포트이기 때문에 컨테이너 즉 가상환경에만 한정된 환경이다. 따라서 컨테이너 밖에서의 명령어는 사용이 불가능함
- 즉, HTTP 요청을 받는 어플리케이션을 사용하기 위해서는 컨테이너 밖에서 온 요청을 컨테이너 안에 있는 어플리케이션에 전달해주어야 되고, 그 전달을 하는 다리가 도커의 포트 포워딩이라고 생각하면 됨!
포트 포워딩 과정
1. 컨테이너 정지시키기
docker container stop $(docker container ls --filter "ancestor=example/echo" -q)
2. 포트 포워딩 명령어 사용하기
- run을 재실행할 때 사용함
-p 옵션 : 포트 포워딩을 지정할 수 있는 명령어이다. 호스트_포트:컨테이너_포트 형식으로 기술하면 됨
호스트 포트 9000을 컨테이너 포트 8080에 연결하도록 하는 포트 포워딩 적용하기
docker container run -d -p 9000:8080 example/echo:latest
- local host 9000에 GET 요청 보내기
curl http://localhost:9000/
컨테이너 ID 추출하기 : ls
- 컨테이너 ID와 생성 시 사용한 이미지 등의 정보를 확인할 수 있다.
- 이때 -q 옵션을 사용하면 컨테이너 ID만 추출할 수 있다.
docker container ls -q
컨테이너 목록 필터링하기
- 특정 조건을 만족하는 컨테이너 목록을 보려면 --fiter 옵션을 사용하면 된다.
docker container ls --filter "필터명=값"
- 원하는 이름과 컨테이너명이 일치하는 컨테이너 목록보기 = name 필터
docker container ls --filter "name=echo"
- 예시 : 정지된 컨테이너 목록 확인하기
dockr container ls --filter "status=exited"
- 컨테이너를 생성한 이미지를 기준으로 하려면 ancestor 필터를 사용한다.
docker container ls --filter "ancestor=example/echo"
도커 컨테이너 정지하기
docker container stop 컨테이너ID_또는_컨테이너명
예시
docker container run -t -d --name echo example/echo:latest
docker container stop echo
컨테이너 재시작하기
docker container restart 컨테이너ID또는컨테이너이름
컨테이너 파기하기
- 컨테이너를 정지시킨 뒤 완전히 삭제하기
docker container rm 컨테이너명_또는_컨테이너ID
- 현재 실행 중인 컨테이너를 억지로 삭제하려면 -f 옵션을 사용한다.
docker container rm -f 컨테이너ID
현재 실행 중인 도커의 표준 출력 연결하기
docker container logs [options] 컨테이너ID_또는_컨테이너명
새로 출력되는 표준 출력 내용 연결하기 : -f
docker container logs -f $(docker container ls --filter "ancestor=jenkins" -q)
실행 중인 컨테이너에서 명령 실행하기 : exec
- 컨테이너에 ssh로 로그인한 것처럼 컨테이너에서 명령을 실행하는 것이 가능하다.
docker container exec [options] 컨테이너ID_또는_컨테이너명 컨테이너에서실행할명령
예시
docker container run -t -d --name echo --rm example/echo:latest
docker container exec echo pwd
-i : 표준 입력 연결 유지
-t : 유사 터미널을 할당하는 옵션
docker container exec -it echo sh
파일 복사하기 : docker container cp
docker container cp [options] 컨테이너ID_또는_컨테이너명:원본파일 대상파일
docker container cp [options] 호스트_원본파일 컨테이너ID_또는_컨테이너명:대상파일
- DOCKERFILE에 포함된 COPY 인스트럭션은 이미지를 빌드할 때 호스트에서 복사해오기 위한 것이고 docker container cp 명령은 컨테이너와 파일을 주고받기 위한 명령임
- 예를 들어서 컨테이너 안에 있는 /echo/main.go 파일을 호스트의 현재 작업 디렉토리로 복사함
docker container cp echo:/echo/main.go
호스트에서 컨테이너로 파일을 복사하는 것
docker container cp dummy.txt echo:/tmp
필요없는 이미지나 컨테이너를 모두 삭제 : docker container prune
- 실행 중이 아닌 모든 컨테이너를 삭제하는 명령어
예시
docker container ls -a # 모든 컨테이너의 상태를 출력해준다.
docker container prune [options]
이미지 삭제하기
docker image prune [options]
시스템에 있는 리소스 삭제하기
- 사용하지 않는 도커 이미지뿐만 아니라 컨테이너 볼륨, 네트워크 등의 모든 도커 리소스를 일괄적으로 삭제하기
docker system prune
시스템 리소스 사용현황 확인하기
-