우분투 · 리눅스 입문 — 26편 (고급 · 완결)

우분투 도커(Docker) 입문 — 이미지·컨테이너·볼륨·compose

"내 컴퓨터에선 되는데"를 끝내는 도구. 앱과 환경을 통째로 담아 어디서든 똑같이 — 26편 입문 시리즈의 마지막 편입니다.

2026년 5월 13일 · 약 8분 · 26편 입문 시리즈 26편 (완결)

docker run·ps·logs·볼륨 마운트 명령과 docker-compose.yml 로 웹+DB 를 한 번에 띄우는 터미널 화면 일러스트 — 우분투 도커 입문을 상징

19편에서 systemd 로 "앱을 항상 떠 있게" 만들었고, 22~25편에서 스크립트·로그·보안을 다뤘죠. 이제 마지막 한 조각 — 도커(Docker). "내 컴퓨터에선 되는데 서버에선 안 돼" 의 원인은 보통 환경 차이(파이썬 버전, 라이브러리, 설정)인데, 도커는 앱 + 그 환경을 통째로 한 덩어리로 묶어 어디서든 똑같이 돌게 합니다. 그리고 컨테이너끼리 격리되니 한 앱이 다른 앱을 망치지도 않고요.

먼저: 19편(systemd)·22편(스크립트)·24편(로그)·25편(보안)을 봤다면 이어집니다. 이 편이 26편 입문 시리즈의 마지막이에요. 순서 — ① 설치·첫 컨테이너 → ② 컨테이너 다루기(run·ps·logs·exec) → ③ 볼륨·네트워크 → ④ docker compose 맛 + 시리즈 완결. 실습은 nginx 같은 공식 이미지로 안전하게.

도커가 뭔데 — 설치하고 첫 컨테이너

핵심 개념 둘: 이미지 = "앱 + 환경"이 통째로 든 읽기 전용 템플릿(예: nginx, python:3.12, postgres). 컨테이너 = 그 이미지를 실행한 인스턴스(같은 이미지로 여러 개 띄울 수 있음). 비유하면 이미지는 "설치 디스크", 컨테이너는 "그걸 깔아 돌리는 실행 중인 머신" — 단 가볍고 빠릅니다(가상머신보다 훨씬).

$ sudo apt install docker.io # 우분투 패키지 (또는 docker.com 공식 스크립트) $ docker --version # 설치 확인 $ sudo docker run hello-world # 첫 컨테이너 — 잘 되면 환영 메시지 # 매번 sudo 치기 싫으면 (단 보안상 주의 — docker 그룹은 사실상 root 권한, 25편 최소 권한 정신 기억): $ sudo usermod -aG docker $USER # 그 후 로그아웃→로그인 (또는 newgrp docker)

이미지를 받아오고, 컨테이너를 띄워봅니다. docker run -d -p 8080:80 --name web nginx-d(백그라운드), -p 호스트:컨테이너(포트 매핑 — 호스트의 8080 으로 들어오면 컨테이너의 80 으로), --name(이름):

$ docker pull nginx # 이미지 받아오기 (run 할 때 없으면 자동으로 받음) $ docker run -d -p 8080:80 --name web nginx $ docker images # 받아둔 이미지 목록 $ docker ps # 실행 중인 컨테이너 (ps -a 면 멈춘 것까지) # → 브라우저에서 http://localhost:8080 으로 nginx 가 보임

컨테이너 다루기 — run·logs·exec·stop·rm

$ docker logs web # 컨테이너 로그 (24편의 로그 보기 — docker logs -f 면 실시간) $ docker exec -it web bash # 컨테이너 "안으로" 들어가 셸 열기 (exit 로 나옴) $ docker stop web # 멈추기 (start 로 다시) $ docker rm web # 컨테이너 삭제 (멈춘 상태에서 — rm -f 면 강제) $ docker rmi nginx # 이미지 삭제 $ docker run --rm -it python:3.12 python # --rm: 끝나면 자동 삭제 — 잠깐 파이썬 써보고 버리기 $ docker system prune # 안 쓰는 컨테이너·이미지·캐시 청소 (디스크 확보 — 15편)
systemd vs Docker (19편과 비교): systemd 는 "이 서버에 설치된 프로그램을 떠 있게" 관리한다면, Docker 는 "이 앱을 환경까지 통째로 캡슐에 담아" 띄웁니다. 둘 다 "재시작·자동 시작"을 하지만 — 환경 충돌이 잦거나 여러 버전을 같이 돌려야 하면 Docker, 시스템 자체의 데몬(SSH·cron 등)이면 systemd. 그리고 Docker 컨테이너를 부팅 시 자동 시작하려면 docker run --restart unless-stopped ... (또는 compose 의 restart:).

볼륨과 네트워크 — 데이터 안 날아가게, 컨테이너끼리 통신

볼륨 — 컨테이너를 지워도 데이터는 남게. 컨테이너 안에 쓴 데이터는 컨테이너를 rm 하면 같이 사라집니다. DB·업로드 파일처럼 영구 데이터는 볼륨(도커가 관리)이나 호스트 폴더 마운트에 둬야 해요:

# 호스트 폴더를 컨테이너에 연결 (-v 호스트경로:컨테이너경로) $ docker run -d -p 8080:80 -v /home/me/site:/usr/share/nginx/html nginx # 도커 관리 볼륨 (DB 에 권장 — 권한·이식성 깔끔) $ docker volume create pgdata $ docker run -d --name db -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres $ docker volume ls # 볼륨 목록 (rm 으로 삭제 — 데이터도 같이 사라지니 주의)

네트워크 (맛만). 컨테이너는 기본적으로 격리돼 있지만, 같은 사용자 네트워크에 두면 컨테이너 이름으로 서로 통신합니다(웹 컨테이너가 db 라는 호스트명으로 DB 컨테이너에 접속). docker network create mynetdocker run --network mynet ....

⚠️ Docker 와 방화벽(17편): Docker 는 -p 로 포트를 열 때 자체적으로 iptables 규칙을 추가하는데, 이게 ufw 를 우회할 수 있습니다 — ufw deny 해뒀는데도 -p 0.0.0.0:5432:5432 로 띄운 DB 가 외부에 노출되는 식. 안전하게: DB 같은 건 -p 127.0.0.1:5432:5432 처럼 로컬에만 바인딩하거나, 컨테이너끼리만 통신하게 하고 외부 포트는 꼭 필요한 것(웹의 80/443)만 여세요. (검색어: "ufw docker" — 해결 설정이 있습니다.)

docker compose 맛 — 그리고 26편 시리즈 완결

웹 + DB 처럼 여러 컨테이너를 매번 긴 docker run 으로 띄우긴 번거롭죠. docker compose 는 그걸 docker-compose.yml 한 파일에 적어두고 한 명령으로 띄웁니다(22편의 "선언적 스크립트"와 비슷한 느낌):

# docker-compose.yml services: web: image: nginx ports: ["8080:80"] restart: unless-stopped # 부팅 시 자동 시작 db: image: postgres environment: { POSTGRES_PASSWORD: secret } volumes: ["pgdata:/var/lib/postgresql/data"] volumes: pgdata:
$ docker compose up -d # 정의된 컨테이너 전부 한 번에 (compose.yml 이 있는 폴더에서) $ docker compose ps # 상태 보기 $ docker compose logs -f web # 한 서비스 로그 $ docker compose down # 전부 내리기 (-v 면 볼륨까지 — 데이터 주의)

(참고: 이 블로그도 WordPress 를 Docker compose 로 돌립니다 — 한 파일에 워드프레스 + DB 컨테이너를 적어두고 up -d 하나로. 환경 충돌 없이, 다른 서버로 옮길 때도 그 파일만 들고 가면 끝.)

26편 입문 시리즈 — 완주!

  1. 1~5편 입문(리눅스란·설치·첫 설정·터미널·디렉토리 구조) ✔
  2. 6~12편 기초(파일·텍스트·nano·권한·사용자·apt·파이프) ✔
  3. 13~20편 중급(vim·프로세스·디스크·네트워크·ufw·SSH·systemd·cron) ✔
  4. 21~26편 고급(셸 스크립트·안전한 스크립트·grep/sed/awk·로그/모니터링·서버 보안·도커) ✔

여기까지가 "리눅스를 무서워하지 않고 다루는" 데 필요한 기본기입니다. 다음 단계로 가고 싶다면 — 더 깊은 컨테이너(여러 서버·쿠버네티스), 인프라 자동화(Ansible·Terraform), 스토리지(LVM·RAID), 본격적인 보안(침입 탐지·감사) 같은 길이 있어요. 하지만 그건 다른 시리즈의 몫이고 — 26편 완주, 축하합니다. 이제 검은 화면이 안 무섭죠?

참고: 본 글은 우분투(docker.io 패키지 / Docker Engine) 기준이며 2026년 5월 13일에 작성되었습니다. 클라우드·기업 환경은 보안 정책(rootless docker, 이미지 스캔 등)이 추가될 수 있고, docker compose 는 v2(플러그인) 기준입니다.

우분투·리눅스 입문 시리즈 — 완결

26편으로 입문 시리즈가 끝났습니다. 1편(리눅스란?)부터 다시 보거나, 다음 단계 콘텐츠를 기다리고 싶다면 — junai.ai/blog 의 "Ubuntu 리눅스 배우기" 카테고리에 26편이 다 모여 있습니다.

© 2026 JUNAI · 우분투·리눅스 입문 시리즈 26편 (완결) · 본 글은 2026년 5월 13일 기준으로 작성되었습니다.

© 2026 주나이테크(주) @JUNAITECH