Haru Utils

CONTAINER RUNTIME

Docker Engine와 Compose 설치

Ubuntu 24.04에 Docker 공식 APT 저장소를 등록하고 Engine·Buildx·Compose 플러그인을 설치한 뒤 로그 회전, 부팅 자동 시작, 포트 노출 보안을 검증합니다.
Docker Engine 설치Docker Compose 설치Ubuntu Docker 공식 저장소docker daemon.jsonDocker 보안
지원 환경Ubuntu Server 24.04 LTS · amd64
예상 시간30
난이도중급
검토일2026-08-28

BEFORE YOU START

시작 전에 준비하세요

01

sudo 권한과 Docker 공식 저장소에 접근 가능한 네트워크

02

기존 컨테이너 런타임·이미지·볼륨의 사용 여부를 확인할 권한

03

이미지와 볼륨을 저장할 /var/lib/docker 및 /var/lib/containerd 용량

04

서비스 중단 가능성이 있는 기존 설치라면 별도 점검 시간과 데이터 백업

권장 대상 Ubuntu 서버에 패키지 관리형 Docker Engine과 docker compose 명령을 운영 기준으로 설치하려는 개발자·운영자

FOLLOW THE RECIPE

8단계 구성·점검 레시피

1
확인시스템을 변경하지 않는 점검 단계

지원 OS·아키텍처·커널 확인

Docker가 공식 지원하는 Ubuntu 24.04와 아키텍처인지, systemd·cgroup 환경이 준비됐는지 확인합니다.

Ubuntu 릴리스
cat /etc/os-release
아키텍처와 커널
dpkg --print-architecture
uname -r
systemd와 cgroup
ps -p 1 -o comm=
stat -fc %T /sys/fs/cgroup
가상화 방식
systemd-detect-virt
제공 업체가 중첩 컨테이너 또는 커널 기능을 제한하는지 함께 확인합니다.
  • Ubuntu 24.04 LTS와 amd64 또는 arm64임을 확인했습니다.
  • PID 1이 systemd이며 cgroup 파일시스템을 확인했습니다.
  • 호스팅 환경이 컨테이너 실행을 허용합니다.
결과 읽기

WSL, LXC 내부, 커스텀 커널은 기능 제약이 있을 수 있습니다. 제공 업체 정책과 Docker의 해당 환경 문서를 먼저 확인합니다.

다음 판단

기존 Docker 계열 패키지와 실행 중 워크로드를 조사합니다.

2
확인시스템을 변경하지 않는 점검 단계

기존 런타임·데이터·포트 사전 점검

Docker 공식 패키지와 충돌할 수 있는 배포판 패키지, 기존 컨테이너와 볼륨, 디스크, 리슨 포트를 확인합니다. 기존 데이터가 있으면 신규 설치 절차로 덮지 않습니다.

충돌 가능 패키지
dpkg -l | grep -E 'docker.io|docker-doc|docker-compose|podman-docker|containerd|runc'
출력이 없을 수 있습니다. 패키지를 바로 제거하지 말고 사용 여부부터 확인합니다.
기존 Docker 실행 상태
command -v docker
sudo systemctl status docker.service --no-pager
미설치 환경에서는 not found 또는 unit 없음이 정상입니다.
기존 워크로드와 볼륨
sudo docker ps -a
sudo docker volume ls
sudo docker network ls
Docker가 이미 설치된 경우에만 실행하고 결과를 백업 계획에 반영합니다.
데이터 경로 용량
df -hT / /var/lib/docker /var/lib/containerd
아직 경로가 없다는 메시지는 신규 설치에서는 정상입니다.
Docker API·주요 포트 확인
sudo ss -lntup | grep -E ':(2375|2376)\b'
출력이 없으면 TCP Docker API가 열려 있지 않은 상태입니다.
  • 기존 Docker·containerd·Podman 패키지의 소유 워크로드를 확인했습니다.
  • 운영 볼륨과 바인드 마운트 백업 여부를 확인했습니다.
  • Docker 데이터 경로의 여유 공간과 별도 마운트 여부를 기록했습니다.
결과 읽기

기존 컨테이너나 볼륨이 있으면 공식 문서의 업그레이드 경로와 백업을 먼저 검토합니다. 충돌 패키지를 무조건 제거하면 서비스가 중단될 수 있습니다.

다음 판단

기존 설치가 없는 호스트에 Docker 공식 서명키와 APT 저장소를 등록합니다.

3
변경패키지·설정·서비스 상태가 달라지는 단계

Docker 공식 APT 저장소와 패키지 설치

편의 설치 스크립트 대신 Docker 공식 APT 저장소를 사용합니다. 기존 키나 sources 파일은 먼저 별도 이름으로 백업합니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
저장소 필수 패키지
sudo apt update
sudo apt install ca-certificates curl gnupg
키링 디렉터리 준비
sudo install -m 0755 -d /etc/apt/keyrings
기존 Docker 키 백업
sudo cp --archive --no-clobber /etc/apt/keyrings/docker.asc /etc/apt/keyrings/docker.asc.<BACKUP_SUFFIX>
기존 파일이 있을 때만 실행하고 아직 존재하지 않는 백업 이름을 사용합니다.
Docker 공식 서명키 받기
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
키 정보 확인
gpg --show-keys --with-fingerprint /etc/apt/keyrings/docker.asc
기존 저장소 파일 백업
sudo cp --archive --no-clobber /etc/apt/sources.list.d/docker.sources /etc/apt/sources.list.d/docker.sources.<BACKUP_SUFFIX>
기존 파일이 있을 때만 실행합니다.
저장소 파일 편집
sudoedit /etc/apt/sources.list.d/docker.sources
아래 내용의 <ARCH>를 dpkg --print-architecture 결과로 바꿉니다.
후보 패키지와 출처 확인
sudo apt update
apt-cache policy docker-ce
Engine·Buildx·Compose 설치
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
설정 예시 · /etc/apt/sources.list.d/docker.sources
Ubuntu 24.04 Docker stable 저장소
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: <ARCH>
Signed-By: /etc/apt/keyrings/docker.asc
Ubuntu 24.04 전용 예제입니다. <ARCH>는 amd64 또는 arm64처럼 실제 dpkg 결과로 바꾸고, 다른 릴리스에는 noble을 사용하지 않습니다.
  • 키 파일과 저장소 URL이 Docker 공식 도메인입니다.
  • apt-cache policy의 docker-ce 후보가 download.docker.com에서 옵니다.
  • Compose는 독립 docker-compose 바이너리가 아니라 docker compose 플러그인으로 설치했습니다.
결과 읽기

apt update의 서명 오류나 Release 파일 오류를 무시하지 않습니다. OS 코드명·시계·프록시·키 파일부터 확인합니다.

다음 판단

컨테이너 로그가 디스크를 채우지 않도록 데몬 기본 로그 드라이버를 설정합니다.

4
주의권한·연결·중단 영향을 확인할 단계

Docker 데몬 로그 회전 설정

Docker 기본 json-file 로그는 회전 없이 커질 수 있습니다. 신규 서버는 회전이 기본인 local 드라이버를 권장하고, 기존 daemon.json이 있으면 키를 병합합니다.

현재 데몬 설정 확인
sudo ls -l /etc/docker/daemon.json
sudo cat /etc/docker/daemon.json
파일이 없다는 메시지는 신규 설정에서는 정상입니다. 기존 내용에 자격증명이 없는지도 확인합니다.
기존 daemon.json 백업
sudo cp --archive --no-clobber /etc/docker/daemon.json /etc/docker/daemon.json.<BACKUP_SUFFIX>
기존 파일이 있을 때만 실행하고 고유한 백업 이름을 사용합니다.
데몬 설정 편집
sudoedit /etc/docker/daemon.json
기존 JSON을 통째로 바꾸지 말고 log-driver 키를 올바른 JSON 문법으로 병합합니다.
데몬 설정 검증
sudo dockerd --validate --config-file=/etc/docker/daemon.json
configuration OK가 확인돼야 서비스를 재시작합니다.
설정 예시 · /etc/docker/daemon.json
신규 파일용 최소 로그 설정
{
  "log-driver": "local"
}
파일이 이미 있으면 이 예제로 덮지 말고 기존 최상위 JSON 객체에 log-driver만 병합합니다. 변경은 새로 생성되는 컨테이너부터 적용됩니다.
  • 기존 daemon.json을 별도 이름으로 백업했습니다.
  • 기존 옵션을 보존해 JSON을 병합했습니다.
  • dockerd --validate가 성공했습니다.
결과 읽기

중복 키, 잘못된 쉼표, systemd 플래그와 daemon.json 옵션 충돌은 Docker 기동 실패 원인이 됩니다.

다음 판단

검증된 설정으로 Docker와 containerd를 시작하고 부팅 자동 시작을 확인합니다.

5
변경패키지·설정·서비스 상태가 달라지는 단계

Docker·containerd 시작과 부팅 활성화

설정 검증 후 서비스를 시작합니다. 이미 운영 컨테이너가 있는 서버에서는 재시작이 미치는 영향을 먼저 확인합니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
서비스 활성화와 시작
sudo systemctl enable docker.service containerd.service
sudo systemctl restart docker.service
기존 컨테이너가 있으면 재시작 정책과 서비스 영향을 점검 시간에 확인합니다.
Docker 서비스 상태
systemctl is-enabled docker.service
systemctl is-active docker.service
systemctl status docker.service --no-pager
containerd 상태
systemctl is-enabled containerd.service
systemctl is-active containerd.service
최근 데몬 로그
sudo journalctl -u docker.service -n 80 --no-pager
  • docker.service와 containerd.service가 active입니다.
  • docker.service가 부팅 시 enabled입니다.
  • journal에 설정 충돌이나 스토리지 오류가 없습니다.
결과 읽기

서비스가 반복 재시작하면 명령을 반복하지 말고 journal과 daemon.json 검증 결과를 확인합니다.

다음 판단

실제 이미지 실행, Compose, 로그 드라이버와 부팅 자동 활성화 상태를 검증합니다.

6
확인시스템을 변경하지 않는 점검 단계

컨테이너·Compose·로그 설정 검증

클라이언트 버전 출력만으로 끝내지 않고 공식 테스트 이미지를 실제로 내려받아 실행하고 서버·Compose·로그 설정을 확인합니다.

클라이언트와 서버 버전
sudo docker version
테스트 컨테이너 실행
sudo docker run --rm hello-world
Docker Hub에서 작은 테스트 이미지를 내려받아 실행 후 자동 제거합니다.
Compose 플러그인
sudo docker compose version
기본 로그 드라이버
sudo docker info --format '{{.LoggingDriver}}'
부팅 활성화와 실패 상태
systemctl is-enabled docker.service containerd.service
systemctl --failed --no-pager
  • hello-world가 확인 메시지를 출력하고 종료했습니다.
  • docker compose version이 정상 출력됩니다.
  • 새 컨테이너의 기본 로그 드라이버가 local입니다.
결과 읽기

이미지 pull만 실패하면 데몬 자체보다 DNS·프록시·외부 통신 문제일 수 있습니다. 클라이언트는 되지만 서버 정보가 없으면 소켓 권한이나 데몬 상태를 확인합니다.

다음 판단

Docker 소켓 권한, API 리슨 주소, 공개 포트와 UFW의 관계를 점검합니다.

7
주의권한·연결·중단 영향을 확인할 단계

소켓 권한과 공개 포트 보안 점검

docker 그룹은 root 수준 권한을 부여하며, 컨테이너 공개 포트는 UFW의 일반 INPUT 규칙보다 먼저 우회될 수 있습니다. 편의를 위해 권한이나 포트를 넓히지 않습니다.

Docker 소켓 권한
ls -l /var/run/docker.sock
getent group docker
Docker API TCP 노출 검사
sudo ss -lntp | grep -E ':(2375|2376)\b'
출력이 없으면 기본 Unix 소켓만 사용하는 상태입니다. 2375가 외부 주소에 열려 있으면 즉시 원인을 확인합니다.
컨테이너 공개 포트 목록
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'
현재 방화벽 상태
sudo ufw status verbose
Docker의 published port는 UFW 규칙만으로 차단된다고 가정하지 않습니다.
데몬 보안 옵션
sudo docker info --format '{{json .SecurityOptions}}'
  • docker 그룹에는 root 권한이 필요한 신뢰된 운영자만 포함합니다.
  • Docker TCP API 2375를 인증 없이 외부에 노출하지 않습니다.
  • 컨테이너 포트는 필요한 호스트 주소와 포트에만 publish합니다.
  • UFW만 믿지 않고 클라우드 방화벽과 Docker 체인 정책을 함께 검토합니다.
  • 컨테이너 이미지는 고정 버전·신뢰 가능한 출처를 사용하고 정기 업데이트합니다.
  • 민감정보는 이미지·Compose 파일·환경변수 출력에 하드코딩하지 않습니다.
결과 읽기

sudo 없는 Docker가 꼭 필요하면 docker 그룹의 root 수준 위험을 승인하거나 공식 Rootless mode를 별도 설계합니다.

다음 판단

설정 문제가 있으면 daemon.json만 복원하고, 완전 제거는 데이터 백업 뒤 별도 승인으로 수행합니다.

8
변경패키지·설정·서비스 상태가 달라지는 단계

데몬 설정 복원 또는 신규 설치 제거

기존 daemon.json이 있던 환경은 확인된 백업을 복원하고, 파일이 없던 신규 환경은 이번 레시피가 만든 파일만 비활성화합니다. 패키지 제거 역시 신규 빈 설치로 확인된 경우에만 수행합니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
중단 전 워크로드·볼륨·설정 이력 확인
sudo docker ps -a
sudo docker volume ls
sudo docker info --format '{{.DockerRootDir}}'
sudo find /etc/docker -maxdepth 1 -type f -name 'daemon.json*' -print
사전 점검 때 daemon.json이 있었는지와 이번 작업에서 만든 고유 백업 파일을 변경 기록과 대조합니다.
설정 복원을 위한 서비스 중지
sudo systemctl stop docker.service docker.socket
실행 중 컨테이너가 없거나 중단 승인을 받은 점검 시간에만 실행합니다.
A. 기존 설정의 확인된 백업 복원
sudo test -f /etc/docker/daemon.json.<BACKUP_SUFFIX> && sudo cp --archive /etc/docker/daemon.json.<BACKUP_SUFFIX> /etc/docker/daemon.json
sudo dockerd --validate --config-file=/etc/docker/daemon.json
사전 점검에서 기존 daemon.json이 있었고 실제 백업 파일의 내용·시각을 확인한 경우에만 실행합니다. test가 실패하면 복원 명령을 진행하지 않습니다.
B. 이번에 새로 만든 daemon.json 비활성화
sudo test -f /etc/docker/daemon.json && sudo test ! -e /etc/docker/daemon.json.disabled && sudo mv /etc/docker/daemon.json /etc/docker/daemon.json.disabled
사전 점검에서 daemon.json이 없었고 이번 레시피가 새로 만든 파일임이 작업 기록으로 확인된 경우에만 A 대신 실행합니다. 기존 파일에는 사용하지 않습니다.
서비스 재시작
sudo systemctl start docker.service
systemctl status docker.service --no-pager
완전 제거 전 containerd 소비자 확인
sudo systemctl status containerd.service --no-pager
sudo ctr namespaces list
daemon.json 복원에는 containerd 중지가 필요하지 않습니다. containerd.io 제거는 Docker 완전 제거가 승인되고 Kubernetes·nerdctl·다른 런타임 등 containerd 소비자가 전혀 없으며 사용 중 namespace도 없음을 확인한 경우에만 진행합니다.
신규 빈 설치의 패키지 제거
dpkg-query -W docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo apt remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
사전 점검에서 해당 패키지가 없었고 이번 레시피가 설치했으며, 완전 제거가 승인되고 보존할 워크로드를 백업한 경우에만 두 번째 명령을 실행합니다. /var/lib/docker, /var/lib/containerd, 이미지, 볼륨은 절대 자동 삭제하지 않습니다.
신규 생성 Docker 저장소 비활성화
sudo test -f /etc/apt/sources.list.d/docker.sources && sudo test ! -e /etc/apt/sources.list.d/docker.sources.disabled && sudo mv /etc/apt/sources.list.d/docker.sources /etc/apt/sources.list.d/docker.sources.disabled
sudo apt update
사전 점검에서 저장소 파일이 없었고 이번 레시피가 만든 파일일 때만 실행합니다. 기존 파일이었다면 확인된 .<BACKUP_SUFFIX> 파일을 복원하고 임의로 비활성화하지 않습니다.
  • 중단 전 컨테이너·볼륨·바인드 마운트 목록을 보관했습니다.
  • 기존 파일 복원(A)과 신규 파일 비활성화(B) 중 사전 점검 기록에 맞는 한 경로만 실행했습니다.
  • 확인된 daemon.json 백업을 복원한 경우 dockerd --validate를 통과했습니다.
  • 패키지를 제거해도 데이터 디렉터리·이미지·볼륨은 삭제하지 않았습니다.
결과 읽기

패키지를 제거해도 /var/lib/docker·/var/lib/containerd 데이터가 남을 수 있습니다. 반대로 이 경로를 성급히 지우면 복구하기 어려우므로 자동 삭제 명령을 제공하지 않습니다.

다음 판단

복구 결과와 영향받은 컨테이너를 기록하고 서비스별 재기동 검증을 수행합니다.

SECURITY CHECK

운영 전 마지막 보안 점검

  • Docker 공식 저장소와 서명키만 사용하고 편의 설치 스크립트를 운영 설치에 사용하지 않습니다.
  • docker 그룹이 root 수준 권한이라는 점을 승인하고 최소 인원만 포함합니다.
  • 인증 없는 Docker TCP API, 특히 2375를 외부 주소에 노출하지 않습니다.
  • published port는 UFW를 우회할 수 있으므로 클라우드 방화벽과 Docker 방화벽 정책을 함께 검토합니다.
  • 로그 회전과 데이터 경로 용량을 모니터링해 디스크 고갈을 예방합니다.
  • 이미지 태그·출처·취약점 업데이트 정책과 비밀정보 주입 방식을 정합니다.

COMMON ERRORS

자주 막히는 지점

Docker 패키지 의존성 충돌

증상
docker-ce 또는 containerd.io 설치 중 Conflicts·held packages 오류가 납니다.
가능한 원인
docker.io, distro containerd, podman-docker 같은 기존 패키지나 고정 버전이 충돌할 수 있습니다.
확인 순서
dpkg -l과 apt-cache policy로 소유 워크로드를 확인하고 백업 후 공식 충돌 패키지 목록에 해당하는 항목만 계획적으로 전환합니다.
트러블슈팅으로 이어보기

Docker 서비스가 반복 재시작함

증상
docker.service가 failed 또는 activating 상태를 반복합니다.
가능한 원인
daemon.json 문법 오류, systemd 옵션 중복, 스토리지·방화벽 초기화 실패일 수 있습니다.
확인 순서
dockerd --validate와 journalctl -u docker.service를 확인하고 daemon.json 백업을 복원합니다.
트러블슈팅으로 이어보기

sudo 없이 Docker 소켓 접근이 거부됨

증상
permission denied while trying to connect to the Docker daemon socket가 표시됩니다.
가능한 원인
기본 Unix 소켓은 root 또는 docker 그룹만 접근할 수 있습니다.
확인 순서
우선 sudo를 사용합니다. 지속적인 비root 운영이 필요하면 docker 그룹의 root 수준 권한과 Rootless mode의 제약을 비교해 별도로 승인합니다.
트러블슈팅으로 이어보기

UFW에서 막았는데 컨테이너 포트가 외부에 보임

증상
UFW deny 정책과 달리 published port에 외부 접속이 됩니다.
가능한 원인
Docker가 NAT 규칙으로 트래픽을 UFW INPUT 처리 전에 전환할 수 있습니다.
확인 순서
publish 주소를 127.0.0.1 또는 필요한 내부 주소로 제한하고 클라우드 방화벽과 Docker 전용 필터 정책을 함께 설계합니다.
트러블슈팅으로 이어보기

컨테이너 로그로 디스크가 가득 참

증상
/var/lib/docker 아래 사용량이 계속 증가합니다.
가능한 원인
기본 json-file 로그에 회전 제한이 없거나 기존 컨테이너가 이전 설정을 유지할 수 있습니다.
확인 순서
컨테이너별 로그 사용량을 확인하고 local 드라이버 또는 크기 제한을 적용한 뒤 기존 컨테이너를 계획적으로 재생성합니다.
트러블슈팅으로 이어보기

PRIMARY REFERENCES

공식 문서

설치 저장소와 지원 버전은 바뀔 수 있습니다. 검토일 이후에는 링크된 공식 문서와 현재 서버의 패키지 후보 버전을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기