DevOps

『Docker』Docker 명령어 및 정리

라즐리 2022. 8. 12. 11:50

설치

# 테스트용 (공식 편의 스크립트)
curl -fsSL https://get.docker.com | sh

# 설치 확인
docker version

편의 스크립트는 공식 문서에서도 운영 환경용으로는 권장하지 않는다.

운영 서버라면 공식 문서의 배포판별 apt/dnf 저장소 방식으로 설치하는 게 맞다.

 

참고로 apt install docker.io는 Docker 공식 패키지가 아니라 배포판이 관리하는 패키지라서 버전이 꽤 뒤처져 있을 수 있다.

매일 치는 것들

# 테스트용으로 띄웠다가 끝나면 알아서 삭제
docker run --rm -it ubuntu:22.04 bash

# 백그라운드 실행 + 포트 연결
docker run -d -p 8080:80 --name web nginx

# 실행 중인 컨테이너 들어가기
docker exec -it web sh

# 로그 (마지막 100줄부터 계속 따라가기)
docker logs -f --tail 100 web

# 파일 넣고 빼기
docker cp ./foo.txt web:/tmp/foo.txt
docker cp web:/tmp/foo.txt ./foo.txt

--rm은 테스트할 때 거의 필수다.

안 붙이면 docker ps -a에 죽은 컨테이너가 태산같이 쌓인다.

리소스 확인

# 컨테이너별 CPU/메모리 사용량
docker stats --no-stream

# 컨테이너 안에서 돌고 있는 프로세스
docker top web

# 호스트 기준 PID 확인
docker inspect --format '{{.State.Pid}}' web

# 디스크를 누가 먹고 있는지
docker system df

docker system df는 정리하기 전에 꼭 먼저 쳐보자.

이미지인지, 빌드 캐시인지, 볼륨인지 알고 지워야 덜 무섭다.

빌드와 푸시

# 빌드 (마지막 점은 빌드 컨텍스트! 빼먹으면 에러)
docker build -t myapp:1.0.0 .

# 멀티 아키텍처 빌드 + 바로 푸시
docker buildx build --platform linux/amd64,linux/arm64 \
  -t registry.example.com/myapp:1.0.0 --push .

# 태그 붙이고 푸시
docker tag myapp:1.0.0 registry.example.com/myapp:1.0.0
docker push registry.example.com/myapp:1.0.0

ARM 맥북에서 빌드한 이미지를 amd64 서버에 올렸다가 exec format error를 한 번이라도 본 사람이라면 --platform의 소중함을 알 것이다.

레지스트리에 태그 불변성(Tag Immutability)이 걸려 있으면 같은 태그로 다시 푸시하는 게 거부된다.

이럴 땐 태그를 덮어쓰려 하지 말고 커밋 SHA 같은 고유값으로 태그를 붙이는 습관을 들이는 게 낫다.

정리하기

# 멈춘 컨테이너, 안 쓰는 네트워크, dangling 이미지, 빌드 캐시 정리
docker system prune

# 컨테이너가 안 쓰는 이미지까지 전부
docker system prune -a

# 종료된(exited) 컨테이너만
docker rm $(docker ps -aq --filter status=exited)

# 안 쓰는 볼륨
docker volume prune

 

  • docker volume prune은 컨테이너에 연결되지 않은 볼륨을 이름 있는 것까지 전부 지운다.
    컨테이너를 잠깐 내려둔 사이에 치면 DB 데이터 볼륨이 날아갈 수 있으니 한 번 더 확인하고 치자.

자주 만나는 에러

1. permission denied ... docker.sock

sudo usermod -aG docker $USER
newgrp docker

자세한 건 예전에 쓴 ECR 업로드 시 Docker 권한 문제 글 참고.

참고로 docker 그룹은 사실상 root 권한이라 공용 서버에서는 신중하게 줘야 한다.

2. 컨테이너가 Exit Code 137로 죽음

docker inspect --format '{{.State.OOMKilled}}' web

true면 메모리 한도를 넘어서 커널이 죽인 거다.

 

3. Storage Driver 확인

docker info --format '{{.Driver}}'