요약
Docker는 애플리케이션과 실행 환경을 컨테이너(Container) 단위로 패키징하고 실행하는 플랫폼입니다. 개발 환경과 운영 환경의 차이를 줄이고, 배포 과정을 일관되게 만들 수 있어 개발, DevOps, CI/CD 환경에서 널리 사용됩니다.
이 글에서는 Docker의 기본 개념, 가상머신(VM)과 컨테이너의 차이, 핵심 구성요소, Ubuntu에서 Docker Engine을 설치하는 방법, Windows/macOS에서 Docker Desktop을 사용하는 방법, Dockerfile과 Docker Compose 예제, 그리고 실무에서 자주 하는 실수를 정리합니다.
기준: Docker 공식 문서, Docker Engine/ Desktop 릴리스 노트, Ubuntu 패키지 정보, Docker Compose 문서, Podman 공식 사이트와 검색 결과를 함께 확인했습니다. Docker는 버전에 따라 설치 명령, 패키지 이름, 지원 정책이 바뀔 수 있으므로 실제 설치 전 공식 문서를 함께 확인하는 것이 좋습니다.
목차
배경
개발자가 자주 겪는 문제 중 하나는 다음과 같습니다.
“내 PC에서는 잘 실행되는데 서버에서는 오류가 납니다.”
이 문제는 보통 운영체제, 런타임, 라이브러리, 환경 변수, 네트워크 설정, 파일 경로 등이 서로 다르기 때문에 발생합니다. Docker는 애플리케이션 실행에 필요한 요소를 이미지(Image)로 묶고, 이를 컨테이너로 실행함으로써 환경 차이를 줄여줍니다.
Docker를 사용하면 다음과 같은 장점이 있습니다.
- 개발 환경과 운영 환경의 차이를 줄일 수 있습니다.
- 애플리케이션 실행 방식을 표준화할 수 있습니다.
- 테스트, 배포, CI/CD 파이프라인을 구성하기 쉬워집니다.
- 여러 서비스를 Docker Compose로 함께 실행할 수 있습니다.
최신 정보 확인 기준
이 글은 단순히 기존 경험만으로 정리하지 않고, 다음 자료를 기준으로 내용을 보강했습니다.
| 확인한 자료 | 반영한 내용 |
|---|---|
| Docker 공식 개념 문서 | 이미지, 컨테이너, 레지스트리, Dockerfile, Compose 개념 |
| Docker Engine Ubuntu 설치 문서 | 공식 APT 저장소 등록, docker-ce 계열 패키지 설치 방식 |
| Docker Engine 릴리스 노트 | Docker Engine 29 계열이 최신 릴리스 라인으로 제공되고 있음을 확인 |
| Docker Desktop 릴리스 노트 | Docker Desktop 업데이트는 점진 배포되며, 오래된 버전은 다운로드 제한이 있을 수 있음을 확인 |
| Docker Compose 설치 문서 | 최신 환경에서는 docker compose 형태의 CLI 플러그인 사용이 일반적임을 확인 |
| Ubuntu 패키지 정보 | Ubuntu 배포판 패키지인 docker.io가 별도로 존재함을 확인 |
| Podman 공식 사이트 및 검색 결과 | Docker 대안으로 Podman이 언급되는 흐름을 확인 |
이 글의 목적은 Docker 입문자가 설치와 기본 사용 흐름을 이해하는 것입니다. 따라서 특정 릴리스의 모든 변경사항을 깊게 다루기보다는, 설치와 운영 판단에 영향을 주는 최신 흐름을 중심으로 반영했습니다.
세부 내용
Docker란 무엇인가?
Docker는 컨테이너 기반 애플리케이션 실행 플랫폼입니다. 컨테이너는 애플리케이션 프로세스를 격리된 환경에서 실행하지만, 가상머신처럼 운영체제 전체를 새로 띄우지는 않습니다.
Docker에서 자주 등장하는 핵심 개념은 다음과 같습니다.
| 개념 | 설명 |
|---|---|
| Image | 애플리케이션 실행에 필요한 파일, 라이브러리, 설정을 담은 읽기 전용 템플릿 |
| Container | 이미지를 실행한 실제 프로세스 단위의 실행 환경 |
| Docker Engine | 컨테이너를 생성하고 실행하는 핵심 런타임 |
| Docker CLI | docker run, docker build, docker ps 같은 명령을 입력하는 도구 |
| Registry | 이미지를 저장하고 배포하는 저장소. 대표적으로 Docker Hub가 있음 |
| Docker Compose | 여러 컨테이너 서비스를 YAML 파일로 정의하고 함께 실행하는 도구 |
Docker와 가상머신의 차이
Docker 컨테이너와 가상머신은 모두 격리된 실행 환경을 제공하지만 구조가 다릅니다.
| 구분 | 가상머신 VM | Docker 컨테이너 |
|---|---|---|
| 격리 방식 | 하이퍼바이저 위에 Guest OS 실행 | Host OS 커널을 공유하며 프로세스 격리 |
| 부팅 속도 | 상대적으로 느림 | 빠름 |
| 리소스 사용량 | 큼 | 상대적으로 작음 |
| 대표 용도 | OS 단위 격리, 강한 격리 환경 | 애플리케이션 패키징, 배포, 개발 환경 통일 |
| 예시 | VMware, VirtualBox, Hyper-V | Docker, Podman |
단, 컨테이너가 항상 VM보다 안전하다는 뜻은 아닙니다. 컨테이너는 호스트 커널을 공유하므로 보안이 중요한 환경에서는 권한, 네트워크, 볼륨 마운트, 이미지 신뢰성 등을 반드시 검토해야 합니다.
Ubuntu에서 Docker Engine 설치하기
Ubuntu에서는 Docker 공식 APT 저장소를 등록한 뒤 Docker Engine을 설치하는 방식이 권장됩니다. 배포판 기본 저장소의 docker.io 패키지도 사용할 수 있지만, 최신 Docker Engine과 Compose 플러그인을 사용하려면 공식 저장소 방식이 더 적합한 경우가 많습니다.
설치 전에 다음 차이를 이해하는 것이 좋습니다.
| 구분 | 설명 | 적합한 경우 |
|---|---|---|
docker-ce |
Docker 공식 저장소에서 제공하는 Docker Community Edition 패키지 | 최신 Docker Engine, Buildx, Compose 플러그인을 공식 문서 기준으로 설치하려는 경우 |
docker.io |
Ubuntu 배포판 저장소에서 제공하는 Docker 패키지 | 배포판 패키지 정책을 따르거나, 조직 표준이 Ubuntu 저장소 패키지인 경우 |
Docker 공식 문서는 기존에 설치된 docker.io, docker-compose, docker-compose-v2, podman-docker, containerd, runc 등이 공식 Docker Engine 패키지와 충돌할 수 있으므로, 설치 전에 충돌 패키지를 제거하는 절차를 안내합니다. 기존 서버에서 작업한다면 무조건 삭제하기 전에 현재 컨테이너와 패키지 의존성을 확인해야 합니다.
아래 예시는 Docker 공식 문서 기준의 설치 흐름입니다.
# 1. 기존 패키지 정보 갱신 및 필수 패키지 설치
sudo apt update
sudo apt install -y ca-certificates curl
# 2. Docker 공식 GPG 키 저장 경로 생성
sudo install -m 0755 -d /etc/apt/keyrings
# 3. Docker 공식 GPG 키 추가
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
# 4. Docker 공식 APT 저장소 등록
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
# 5. 패키지 정보 갱신
sudo apt update
# 6. Docker Engine 및 관련 플러그인 설치
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
설치 후 다음 명령어로 Docker가 정상 동작하는지 확인할 수 있습니다.
sudo docker run hello-world
정상적으로 설치되었다면 Docker가 테스트 이미지를 내려받고 Hello from Docker! 메시지를 출력합니다.
sudo 없이 Docker 실행하기
Linux에서 Docker 명령을 매번 sudo 없이 실행하려면 현재 사용자를 docker 그룹에 추가할 수 있습니다.
sudo usermod -aG docker $USER
그 다음 로그아웃 후 다시 로그인하거나, 아래 명령으로 현재 세션에 그룹 변경을 적용할 수 있습니다.
newgrp docker
이후 다음 명령으로 확인합니다.
docker run hello-world
주의할 점은 docker 그룹 권한이 사실상 호스트 시스템에 대한 높은 권한으로 이어질 수 있다는 것입니다. 운영 서버에서는 사용자 권한 정책을 신중히 정해야 합니다.
Windows와 macOS에서 Docker 설치하기
Windows와 macOS에서는 일반적으로 Docker Desktop을 설치합니다. Docker Desktop은 Docker Engine, Docker CLI, Docker Compose, GUI 관리 도구를 함께 제공합니다.
Docker Desktop은 서버용 Docker Engine과 동일한 설치 경험이 아닙니다. Windows/macOS에서 Linux 컨테이너를 실행하기 위해 내부적으로 가상화 계층이나 WSL 2 기반 환경을 사용합니다. 또한 Docker Desktop 릴리스 노트에 따르면 업데이트는 점진적으로 배포될 수 있고, 최신 버전이 모든 사용자에게 즉시 보이지 않을 수 있습니다.
설치 흐름은 다음과 같습니다.
- Docker 공식 사이트에서 Docker Desktop을 다운로드합니다.
- 운영체제에 맞는 설치 파일을 실행합니다.
- Windows의 경우 WSL 2 기반 실행 환경을 사용하는 것이 일반적입니다.
- 설치 후 터미널에서 다음 명령을 실행합니다.
docker version
docker run hello-world
Windows와 macOS는 Linux와 내부 구조가 다르므로, Docker Desktop이 가상화 계층 또는 WSL 2를 통해 Linux 컨테이너 실행 환경을 제공합니다.
Docker 기본 명령어
Docker 설치 후 자주 사용하는 명령어는 다음과 같습니다.
# Ubuntu 컨테이너를 대화형 터미널로 실행
docker run -it ubuntu bash
# 실행 중인 컨테이너 목록 확인
docker ps
# 전체 컨테이너 목록 확인
docker ps -a
# 이미지 목록 확인
docker images
# 컨테이너 중지
docker stop <container_id>
# 컨테이너 삭제
docker rm <container_id>
# 이미지 삭제
docker rmi <image_id>
<container_id>와 <image_id>는 실제 환경에 맞게 바꿔야 합니다.
Docker 이미지와 컨테이너 실행 흐름
Docker를 처음 사용할 때 가장 헷갈리는 부분은 이미지와 컨테이너의 관계입니다. 이미지는 실행 템플릿이고, 컨테이너는 그 이미지를 실제로 실행한 인스턴스입니다.
일반적인 흐름은 다음과 같습니다.
Dockerfile 작성
↓
docker build로 이미지 생성
↓
docker run으로 컨테이너 실행
↓
docker logs / docker exec로 상태 확인
↓
docker stop / docker rm으로 정리
예를 들어 Nginx 이미지를 실행하면 다음과 같습니다.
docker run -d --name sample-nginx -p 8080:80 nginx:stable
브라우저에서 http://localhost:8080에 접속하면 컨테이너 안의 Nginx가 응답합니다. 정리할 때는 다음 명령을 사용합니다.
docker stop sample-nginx
docker rm sample-nginx
간단한 Dockerfile 예제
Dockerfile은 애플리케이션 이미지를 만들기 위한 빌드 정의 파일입니다. 아래는 정적 HTML 파일을 Nginx로 서비스하는 가장 단순한 예제입니다.
FROM nginx:stable
COPY ./index.html /usr/share/nginx/html/index.html
같은 디렉터리에 index.html을 만듭니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>Docker Test</title>
</head>
<body>
<h1>Hello Docker</h1>
</body>
</html>
이미지를 빌드하고 실행합니다.
docker build -t sample-nginx-page .
docker run -d --name sample-page -p 8080:80 sample-nginx-page
확인은 다음 명령으로 할 수 있습니다.
curl http://localhost:8080
테스트가 끝나면 컨테이너를 정리합니다.
docker stop sample-page
docker rm sample-page
이 예제는 Docker로 재현 가능한 범위의 단순 예제입니다. 운영 환경에서는 이미지 태그, 보안 스캔, 배포 방식, 로그 수집, 리버스 프록시 구성을 추가로 고려해야 합니다.
Docker Compose 예제
Docker Compose를 사용하면 여러 컨테이너를 하나의 YAML 파일로 정의할 수 있습니다. 최신 Docker 환경에서는 예전의 docker-compose 명령보다 Docker CLI 플러그인 형태인 docker compose 명령을 사용하는 흐름이 일반적입니다.
예를 들어 PostgreSQL 컨테이너를 실행하는 기본 예제는 다음과 같습니다.
services:
postgres:
image: postgres:16
container_name: sample-postgres
ports:
- "5432:5432"
environment:
POSTGRES_DB: sampledb
POSTGRES_USER: sampleuser
POSTGRES_PASSWORD: "****"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
비밀번호, 토큰, API 키 같은 민감정보는 예제에서도 실제 값을 노출하지 않고 ****로 표기해야 합니다. 실제 운영 환경에서는 .env 파일, Secret Manager, CI/CD Secret 기능 등을 사용하는 것이 좋습니다.
실행 명령은 다음과 같습니다.
docker compose up -d
중지하려면 다음 명령을 사용합니다.
docker compose down
볼륨까지 삭제하려면 다음 명령을 사용할 수 있지만, 데이터가 삭제되므로 주의해야 합니다.
docker compose down -v
모범 사례
공식 이미지와 신뢰할 수 있는 이미지를 사용한다
Docker Hub에는 다양한 이미지가 있지만, 모든 이미지가 안전하거나 최신 상태인 것은 아닙니다. 가능하면 공식 이미지 또는 신뢰할 수 있는 벤더의 이미지를 사용해야 합니다.
태그를 명확히 지정한다
운영 환경에서는 latest 태그만 사용하는 것을 피하는 것이 좋습니다.
image: postgres:16
처럼 버전을 명시하면 예기치 않은 버전 변경으로 인한 장애를 줄일 수 있습니다.
환경 변수와 설정 파일을 분리한다
이미지 안에 환경별 설정을 고정해 넣으면 개발, 테스트, 운영 환경을 분리하기 어렵습니다. 데이터베이스 주소, 포트, 실행 모드처럼 환경마다 달라지는 값은 Docker Compose의 environment, .env 파일, 배포 시스템의 설정 관리 기능을 사용하는 것이 좋습니다.
문서 예시에서는 민감한 값이 필요한 경우 실제 값을 쓰지 않고 다음처럼 마스킹합니다.
environment:
POSTGRES_PASSWORD: "****"
운영 환경에서는 단순 .env 파일만으로 충분하지 않을 수 있으므로, 조직의 배포 환경에 맞는 Secret Manager나 CI/CD Secret 기능을 검토해야 합니다.
볼륨과 네트워크를 명확히 관리한다
데이터베이스처럼 상태를 저장하는 서비스는 컨테이너가 삭제되어도 데이터가 유지되도록 볼륨을 사용해야 합니다.
volumes:
postgres_data:
또한 여러 서비스가 함께 동작하는 경우 Docker Compose 네트워크 구성을 이해하고 서비스 이름으로 통신하는 방식을 사용하는 것이 좋습니다.
운영 환경에서는 보안 설정을 검토한다
운영 환경에서는 다음 항목을 반드시 검토해야 합니다.
- 컨테이너 권한
- 루트 사용자 실행 여부
- 호스트 디렉터리 마운트 범위
- Docker socket 노출 여부
- 이미지 취약점 스캔
- 네트워크 포트 공개 범위
- 로그와 모니터링 설정
Docker와 Podman 같은 대안을 함께 검토한다
Docker가 컨테이너 생태계에서 가장 널리 알려진 도구인 것은 맞지만, 모든 환경에서 Docker만 정답인 것은 아닙니다. 최근 컨테이너 운영 환경에서는 Podman 같은 대안도 함께 검토됩니다.
| 구분 | Docker | Podman |
|---|---|---|
| 사용성 | Docker Desktop, Docker Engine, Docker Compose 생태계가 넓음 | Docker CLI와 유사한 사용 경험 제공 |
| 데몬 구조 | Docker daemon 중심 구조 | daemonless 구조를 특징으로 함 |
| 적합한 경우 | 개발 환경 표준화, Compose 기반 로컬 개발, Docker Hub 생태계 활용 | rootless 컨테이너, 리눅스 서버 중심 운영, 특정 보안 정책이 중요한 환경 |
입문자나 일반적인 개발 환경에서는 Docker로 시작하는 것이 쉽습니다. 다만 운영 환경의 보안 정책, rootless 요구사항, Kubernetes 연계 방식에 따라 Podman 같은 대안도 비교할 수 있습니다.
흔한 실수
docker.io와 docker-ce를 혼동한다
Ubuntu에서 apt install docker.io로 설치할 수도 있지만, Docker 공식 문서에서는 공식 저장소를 등록한 뒤 docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin, docker-compose-plugin을 설치하는 방식을 안내합니다.
조직이나 서버 정책에 따라 배포판 패키지를 사용할 수도 있으므로, 설치 목적과 유지보수 정책을 기준으로 선택해야 합니다.
sudo 없이 Docker를 쓰기 위해 권한을 무조건 부여한다
docker 그룹에 사용자를 추가하면 편리하지만, 보안적으로 강한 권한을 부여하는 것과 비슷한 효과가 있을 수 있습니다. 개인 개발 환경과 운영 서버의 권한 정책은 다르게 접근해야 합니다.
컨테이너를 VM처럼 사용한다
컨테이너 내부에 계속 접속해서 수동으로 설정을 바꾸는 방식은 재현성이 떨어집니다. 가능하면 Dockerfile, Compose 파일, 환경 변수로 실행 환경을 코드처럼 관리하는 것이 좋습니다.
데이터를 컨테이너 내부에만 저장한다
컨테이너는 삭제될 수 있습니다. 데이터베이스나 업로드 파일처럼 유지되어야 하는 데이터는 볼륨 또는 외부 스토리지에 저장해야 합니다.
FAQ
Ubuntu에서 Docker 설치 후 권한 오류가 나면 어떻게 해야 하나요?
permission denied while trying to connect to the Docker daemon socket 오류가 발생하면 현재 사용자가 Docker 데몬 소켓에 접근할 권한이 없다는 의미입니다. 개발 환경에서는 사용자를 docker 그룹에 추가한 뒤 다시 로그인하거나 newgrp docker를 실행해 해결할 수 있습니다.
sudo usermod -aG docker $USER
newgrp docker
단, docker 그룹은 높은 권한을 가질 수 있으므로 운영 서버에서는 사용자 권한 정책을 먼저 검토해야 합니다.
docker compose 명령이 동작하지 않으면 무엇을 확인해야 하나요?
최신 Docker 설치 방식에서는 Compose가 별도 docker-compose 바이너리가 아니라 Docker CLI 플러그인으로 제공되는 경우가 많습니다. 다음 명령으로 Compose 플러그인이 설치되어 있는지 확인합니다.
docker compose version
Ubuntu에서 공식 저장소 방식으로 설치한다면 docker-compose-plugin 패키지가 포함되어 있는지 확인합니다.
sudo apt install docker-compose-plugin
Docker Desktop 없이 Linux 서버에서 Docker를 사용할 수 있나요?
가능합니다. Linux 서버에서는 일반적으로 Docker Desktop이 아니라 Docker Engine을 설치해 사용합니다. Docker Desktop은 Windows/macOS 개발 환경에서 Docker를 쉽게 사용하기 위한 도구에 가깝고, Linux 서버 운영 환경에서는 Docker Engine과 Compose 플러그인만 설치하는 구성이 흔합니다.
Docker 설치 확인은 어떤 명령으로 하나요?
설치 후에는 다음 명령으로 Docker CLI와 Docker Engine 상태를 확인할 수 있습니다.
docker version
docker run hello-world
docker run hello-world는 테스트 이미지를 내려받아 컨테이너 실행이 가능한지 확인하는 가장 기본적인 검증 방법입니다.
결론
Docker는 애플리케이션 실행 환경을 컨테이너로 표준화해 개발, 테스트, 배포 과정을 일관되게 만드는 도구입니다. 특히 개발 환경 차이로 인한 문제를 줄이고, CI/CD와 마이크로서비스 환경에서 큰 장점을 제공합니다.
Ubuntu에서는 Docker 공식 저장소를 등록한 뒤 Docker Engine과 Compose 플러그인을 설치하는 방식이 일반적이며, Windows와 macOS에서는 Docker Desktop을 사용하는 방식이 가장 접근하기 쉽습니다.
다만 Docker는 단순한 실행 도구가 아니라 권한, 네트워크, 볼륨, 이미지 보안까지 함께 고려해야 하는 플랫폼입니다. 개발 환경에서는 빠르게 시작하되, 운영 환경에서는 보안과 유지보수 정책을 반드시 함께 검토해야 합니다.
참고 자료
- Docker Docs: What is Docker? — https://docs.docker.com/get-started/docker-overview/
- Docker Docs: Install Docker Engine on Ubuntu — https://docs.docker.com/engine/install/ubuntu/
- Docker Docs: Linux post-installation steps for Docker Engine — https://docs.docker.com/engine/install/linux-postinstall/
- Docker Docs: Docker Desktop — https://docs.docker.com/desktop/
- Docker Docs: Docker Compose installation — https://docs.docker.com/compose/install/
- Docker Docs: Dockerfile reference — https://docs.docker.com/reference/dockerfile/
- Docker Docs: Docker Engine release notes — https://docs.docker.com/engine/release-notes/
- Docker Docs: Docker Desktop release notes — https://docs.docker.com/desktop/release-notes/
- Ubuntu Packages: docker.io — https://packages.ubuntu.com/search?keywords=docker.io
- Podman Official Site — https://podman.io/