공공부하자개발 · 영어 학습 노트
리눅스
리눅스 운영RHEL 에서 배포·운영하기0/13 완료
  • 01셸 기본과 파일 시스템
  • 02텍스트 처리 (grep·sed·awk)
  • 03프로세스·서비스 관리 (systemd)
  • 04자바 애플리케이션 배포
  • 05Tomcat·nginx 배포·재기동
  • 06로그·디스크 운영 (logrotate·cron)
  • 07네트워크 진단 (ss·curl·firewalld)
  • 08셸 스크립트 (운영 자동화)
  • 09장애 대응 (jstack·jmap·OOM killer·FD)
  • 10보안 기초 (ssh 강화·SELinux·감사 로그)
  • 11컨테이너 기초 (podman)
  • 12백업·복구 (설정·릴리스·DB 덤프)
  • 13Docker 실무
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 리눅스 운영 › 11 / 13

컨테이너 기초 (podman)

섹션 7진행 0 / 13
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

2. 핵심 원리

2.1 이미지와 컨테이너

이미지는 읽기 전용 파일 묶음이고 컨테이너는 그 이미지를 실행한 프로세스입니다. 이미지 하나로 컨테이너를 여러 개 띄울 수 있습니다.

개념 비유
이미지 jar 파일
컨테이너 실행 중인 java 프로세스
레지스트리 이미지 저장소 (사내 Nexus 등)
볼륨 컨테이너 밖에 두는 폴더

컨테이너를 지우면 안의 파일도 사라집니다. 로그와 데이터는 볼륨으로 밖에 둡니다.

2.2 Containerfile

이미지를 만드는 레시피입니다. docker 의 Dockerfile 과 같은 문법이고 이름만 다릅니다.

지시어 뜻
FROM 베이스 이미지
USER 실행 사용자
WORKDIR 작업 폴더
COPY 파일 넣기
ENV 환경 변수
EXPOSE 문서용 포트 표시
ENTRYPOINT 시작 명령

FROM registry.access.redhat.com/ubi9/openjdk-21-runtime 이 RHEL 계열의 공식 자바 베이스입니다. JDK 가 이미 들어 있어 jar 만 복사하면 됩니다.

2.3 ENTRYPOINT 와 PID 1

컨테이너의 첫 프로세스가 PID 1 이고 podman stop 은 그 프로세스에 TERM 을 보냅니다. 셸이 PID 1 이면 자바에 신호가 전달되지 않습니다.

text
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /opt/myapp/app.jar"]

exec 가 셸을 자바로 교체해 자바가 PID 1 이 됩니다. 운영 묶음 03 의 완전 종료 흐름이 컨테이너에서도 그대로 동작하려면 이 형태가 필요합니다. $JAVA_OPTS 를 펼치기 위해 sh -c 를 거칩니다.

2.4 빌드와 이미지 관리

bash
podman build -t myapp:1.0 .            # 현재 폴더의 Containerfile
podman images                          # 목록
podman tag myapp:1.0 myapp:latest      # 별칭
podman rmi myapp:1.0                   # 삭제
podman image prune -f                  # 안 쓰는 중간 이미지 정리

-t 이름:태그 에서 태그를 버전으로 씁니다. latest 만 쓰면 어느 버전이 돌고 있는지 알 수 없어 롤백이 어렵습니다.

2.5 실행 옵션

bash
podman run -d --name myapp -p 8080:8080 \
  -v /opt/myapp/logs:/opt/myapp/logs:Z \
  -e JAVA_OPTS='-Xmx512m' \
  --restart=on-failure myapp:1.0
옵션 뜻
-d 백그라운드
--name 이름
-p 호스트:컨테이너 포트 연결
-v 호스트:컨테이너:Z 볼륨, SELinux 라벨
-e 환경 변수
--restart 죽으면 재시작

:Z 가 없으면 SELinux 가 컨테이너의 폴더 접근을 막아 Permission denied 가 납니다. 10 레슨의 SELinux 규칙이 여기서 볼륨 라벨로 나타납니다.

2.6 상태·로그·안으로

명령 뜻
podman ps 실행 중 목록
podman ps -a 정지된 것 포함
podman logs -f --tail 50 myapp 로그 따라가기
podman stats --no-stream CPU·메모리
podman exec -it myapp sh 안에서 셸
podman inspect myapp 상세 JSON

podman logs 는 앱의 stdout 을 보여 줍니다. 파일 로그를 쓰는 앱은 볼륨으로 뺀 폴더를 tail -f 합니다. exec 로 들어가 jps·jstack 을 쓸 수 있어 운영 묶음 09 의 진단이 그대로 됩니다.

2.7 정지와 삭제

bash
podman stop -t 30 myapp          # TERM 후 30초 기다리고 KILL
podman start myapp
podman restart myapp
podman rm -f myapp               # 실행 중이어도 삭제

-t 기본값은 10초입니다. Spring 의 완전 종료 시간보다 길게 줍니다. 컨테이너를 지워도 이미지와 볼륨은 남습니다.

2.8 JVM 메모리와 컨테이너 한도

bash
podman run -d --memory=1g -e JAVA_OPTS='-XX:MaxRAMPercentage=75' myapp:1.0

JDK 21 은 컨테이너 메모리 한도를 인식합니다. -Xmx 를 고정하는 대신 MaxRAMPercentage 로 한도의 비율을 주면 한도를 바꿔도 JVM 이 따라갑니다. 한도 없이 띄우면 호스트 전체 메모리를 기준으로 삼아 운영 묶음 04 의 OOM killer 문제가 그대로 생깁니다.

2.9 systemd 등록: quadlet

podman 4.4 이상은 .container 파일을 두면 systemd 유닛이 자동 생성됩니다. 운영 묶음 03 의 유닛 파일과 같은 형식에 [Container] 절이 추가된 것입니다.

ini
# /etc/containers/systemd/myapp.container
[Unit]
Description=MyApp container
After=network-online.target
[Container]
Image=localhost/myapp:1.0
ContainerName=myapp
PublishPort=8080:8080
Volume=/opt/myapp/logs:/opt/myapp/logs:Z
Environment=JAVA_OPTS=-Xmx512m
[Service]
Restart=on-failure
TimeoutStopSec=40
[Install]
WantedBy=multi-user.target
bash
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f

podman run 옵션이 [Container] 키로 바뀌었을 뿐입니다. 이후 systemctl·journalctl 로 다른 서비스와 똑같이 다룹니다.

2.10 rootless 실행

일반 사용자로 컨테이너를 띄울 수 있습니다. 앱이 뚫려도 그 사용자 권한뿐이라 안전합니다.

bash
podman run -d -p 8080:8080 myapp:1.0          # myapp 계정으로 그대로
loginctl enable-linger myapp                  # 로그아웃해도 유지
systemctl --user enable --now myapp           # 사용자 단위 유닛

1024 미만 포트는 rootless 로 못 엽니다. 80 은 앞단 nginx 나 sysctl net.ipv4.ip_unprivileged_port_start=80 으로 해결합니다.

2.11 폐쇄망 반입

bash
podman save -o myapp-1.0.tar myapp:1.0        # 반출: 파일로
sha256sum myapp-1.0.tar > myapp-1.0.tar.sha256
# 매체로 이동
sha256sum -c myapp-1.0.tar.sha256             # 반입: 확인
podman load -i myapp-1.0.tar                  # 등록
podman images | grep myapp

베이스 이미지도 같은 방식으로 한 번 반입해 두면 서버에서 빌드할 수 있습니다. 사내 레지스트리가 있으면 podman tag 후 podman push registry.corp/myapp:1.0 으로 올려 여러 서버가 pull 합니다.

2.12 정리와 용량

bash
podman ps -a --filter status=exited      # 정지된 컨테이너
podman container prune -f                # 정지된 것 삭제
podman image prune -a -f                 # 안 쓰는 이미지 전부
podman system df                         # 이미지·컨테이너·볼륨 용량

버전마다 이미지를 남기면 수 GB 씩 쌓입니다. 운영 묶음 06 의 디스크 점검에 podman system df 를 추가합니다.

핵심 원리
  • 2.1 이미지와 컨테이너
  • 2.2 Containerfile
  • 2.3 ENTRYPOINT 와 PID 1
  • 2.4 빌드와 이미지 관리
  • 2.5 실행 옵션
  • 2.6 상태·로그·안으로
  • 2.7 정지와 삭제
  • 2.8 JVM 메모리와 컨테이너 한도
  • 2.9 systemd 등록: quadlet
  • 2.10 rootless 실행
  • 2.11 폐쇄망 반입
  • 2.12 정리와 용량
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제