프로젝트

Docker(1) : 도커 공부 정리

SolartheNomad 2023. 6. 19. 13:35

프로젝트 배포 및 이식성 향상을 위해서 도커를 공부하게 되었다. 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

 

시스템 리소스 사용현황 확인하기