sudo 권한과 Docker 공식 저장소에 접근 가능한 네트워크
CONTAINER RUNTIME
Docker Engine와 Compose 설치
Ubuntu 24.04에 Docker 공식 APT 저장소를 등록하고 Engine·Buildx·Compose 플러그인을 설치한 뒤 로그 회전, 부팅 자동 시작, 포트 노출 보안을 검증합니다.BEFORE YOU START
시작 전에 준비하세요
기존 컨테이너 런타임·이미지·볼륨의 사용 여부를 확인할 권한
이미지와 볼륨을 저장할 /var/lib/docker 및 /var/lib/containerd 용량
서비스 중단 가능성이 있는 기존 설치라면 별도 점검 시간과 데이터 백업
권장 대상 Ubuntu 서버에 패키지 관리형 Docker Engine과 docker compose 명령을 운영 기준으로 설치하려는 개발자·운영자
FOLLOW THE RECIPE
8단계 구성·점검 레시피
지원 OS·아키텍처·커널 확인
Docker가 공식 지원하는 Ubuntu 24.04와 아키텍처인지, systemd·cgroup 환경이 준비됐는지 확인합니다.
cat /etc/os-releasedpkg --print-architecture
uname -rps -p 1 -o comm=
stat -fc %T /sys/fs/cgroupsystemd-detect-virt제공 업체가 중첩 컨테이너 또는 커널 기능을 제한하는지 함께 확인합니다.- Ubuntu 24.04 LTS와 amd64 또는 arm64임을 확인했습니다.
- PID 1이 systemd이며 cgroup 파일시스템을 확인했습니다.
- 호스팅 환경이 컨테이너 실행을 허용합니다.
WSL, LXC 내부, 커스텀 커널은 기능 제약이 있을 수 있습니다. 제공 업체 정책과 Docker의 해당 환경 문서를 먼저 확인합니다.
기존 Docker 계열 패키지와 실행 중 워크로드를 조사합니다.
기존 런타임·데이터·포트 사전 점검
Docker 공식 패키지와 충돌할 수 있는 배포판 패키지, 기존 컨테이너와 볼륨, 디스크, 리슨 포트를 확인합니다. 기존 데이터가 있으면 신규 설치 절차로 덮지 않습니다.
dpkg -l | grep -E 'docker.io|docker-doc|docker-compose|podman-docker|containerd|runc'출력이 없을 수 있습니다. 패키지를 바로 제거하지 말고 사용 여부부터 확인합니다.command -v docker
sudo systemctl status docker.service --no-pager미설치 환경에서는 not found 또는 unit 없음이 정상입니다.sudo docker ps -a
sudo docker volume ls
sudo docker network lsDocker가 이미 설치된 경우에만 실행하고 결과를 백업 계획에 반영합니다.df -hT / /var/lib/docker /var/lib/containerd아직 경로가 없다는 메시지는 신규 설치에서는 정상입니다.sudo ss -lntup | grep -E ':(2375|2376)\b'출력이 없으면 TCP Docker API가 열려 있지 않은 상태입니다.- 기존 Docker·containerd·Podman 패키지의 소유 워크로드를 확인했습니다.
- 운영 볼륨과 바인드 마운트 백업 여부를 확인했습니다.
- Docker 데이터 경로의 여유 공간과 별도 마운트 여부를 기록했습니다.
기존 컨테이너나 볼륨이 있으면 공식 문서의 업그레이드 경로와 백업을 먼저 검토합니다. 충돌 패키지를 무조건 제거하면 서비스가 중단될 수 있습니다.
기존 설치가 없는 호스트에 Docker 공식 서명키와 APT 저장소를 등록합니다.
Docker 공식 APT 저장소와 패키지 설치
편의 설치 스크립트 대신 Docker 공식 APT 저장소를 사용합니다. 기존 키나 sources 파일은 먼저 별도 이름으로 백업합니다.
sudo apt update
sudo apt install ca-certificates curl gnupgsudo install -m 0755 -d /etc/apt/keyringssudo cp --archive --no-clobber /etc/apt/keyrings/docker.asc /etc/apt/keyrings/docker.asc.<BACKUP_SUFFIX>기존 파일이 있을 때만 실행하고 아직 존재하지 않는 백업 이름을 사용합니다.sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascgpg --show-keys --with-fingerprint /etc/apt/keyrings/docker.ascsudo 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-cesudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginTypes: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: <ARCH>
Signed-By: /etc/apt/keyrings/docker.ascUbuntu 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 코드명·시계·프록시·키 파일부터 확인합니다.
컨테이너 로그가 디스크를 채우지 않도록 데몬 기본 로그 드라이버를 설정합니다.
Docker 데몬 로그 회전 설정
Docker 기본 json-file 로그는 회전 없이 커질 수 있습니다. 신규 서버는 회전이 기본인 local 드라이버를 권장하고, 기존 daemon.json이 있으면 키를 병합합니다.
sudo ls -l /etc/docker/daemon.json
sudo cat /etc/docker/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.jsonconfiguration OK가 확인돼야 서비스를 재시작합니다.{
"log-driver": "local"
}파일이 이미 있으면 이 예제로 덮지 말고 기존 최상위 JSON 객체에 log-driver만 병합합니다. 변경은 새로 생성되는 컨테이너부터 적용됩니다.- 기존 daemon.json을 별도 이름으로 백업했습니다.
- 기존 옵션을 보존해 JSON을 병합했습니다.
- dockerd --validate가 성공했습니다.
중복 키, 잘못된 쉼표, systemd 플래그와 daemon.json 옵션 충돌은 Docker 기동 실패 원인이 됩니다.
검증된 설정으로 Docker와 containerd를 시작하고 부팅 자동 시작을 확인합니다.
Docker·containerd 시작과 부팅 활성화
설정 검증 후 서비스를 시작합니다. 이미 운영 컨테이너가 있는 서버에서는 재시작이 미치는 영향을 먼저 확인합니다.
sudo systemctl enable docker.service containerd.service
sudo systemctl restart docker.service기존 컨테이너가 있으면 재시작 정책과 서비스 영향을 점검 시간에 확인합니다.systemctl is-enabled docker.service
systemctl is-active docker.service
systemctl status docker.service --no-pagersystemctl is-enabled containerd.service
systemctl is-active containerd.servicesudo journalctl -u docker.service -n 80 --no-pager- docker.service와 containerd.service가 active입니다.
- docker.service가 부팅 시 enabled입니다.
- journal에 설정 충돌이나 스토리지 오류가 없습니다.
서비스가 반복 재시작하면 명령을 반복하지 말고 journal과 daemon.json 검증 결과를 확인합니다.
실제 이미지 실행, Compose, 로그 드라이버와 부팅 자동 활성화 상태를 검증합니다.
컨테이너·Compose·로그 설정 검증
클라이언트 버전 출력만으로 끝내지 않고 공식 테스트 이미지를 실제로 내려받아 실행하고 서버·Compose·로그 설정을 확인합니다.
sudo docker versionsudo docker run --rm hello-worldDocker Hub에서 작은 테스트 이미지를 내려받아 실행 후 자동 제거합니다.sudo docker compose versionsudo 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의 관계를 점검합니다.
소켓 권한과 공개 포트 보안 점검
docker 그룹은 root 수준 권한을 부여하며, 컨테이너 공개 포트는 UFW의 일반 INPUT 규칙보다 먼저 우회될 수 있습니다. 편의를 위해 권한이나 포트를 넓히지 않습니다.
ls -l /var/run/docker.sock
getent group dockersudo ss -lntp | grep -E ':(2375|2376)\b'출력이 없으면 기본 Unix 소켓만 사용하는 상태입니다. 2375가 외부 주소에 열려 있으면 즉시 원인을 확인합니다.sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'sudo ufw status verboseDocker의 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만 복원하고, 완전 제거는 데이터 백업 뒤 별도 승인으로 수행합니다.
데몬 설정 복원 또는 신규 설치 제거
기존 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실행 중 컨테이너가 없거나 중단 승인을 받은 점검 시간에만 실행합니다.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가 실패하면 복원 명령을 진행하지 않습니다.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-pagersudo systemctl status containerd.service --no-pager
sudo ctr namespaces listdaemon.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, 이미지, 볼륨은 절대 자동 삭제하지 않습니다.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
공식 문서
- Docker Docs · Install Docker Engine on Ubuntu
- Docker Docs · Linux post-installation steps
- Docker Docs · Configure logging drivers
- Docker Docs · Packet filtering and firewalls
설치 저장소와 지원 버전은 바뀔 수 있습니다. 검토일 이후에는 링크된 공식 문서와 현재 서버의 패키지 후보 버전을 함께 확인하세요.