폐쇄망 Docker 설치는 설치 RPM과 베이스 이미지를 함께 준비하는 작업이다. Docker 설치에 성공하더라도 Java 21 베이스 이미지가 없으면 이미지 빌드 단계에서 다시 막힐 수 있다.
이 글에서는 SUSE Linux Enterprise Server 15 SP7을 기준으로 외부망에서 가져와야 할 파일, containerd 누락 대응, 폐쇄망 설치, Java 21 기반 이미지 빌드까지 순서대로 정리한다.
예제는 x86_64 서버와 root 권한을 기준으로 한다. 경로와 이미지 이름은 예시이며 실제 작업 환경에 맞게 변경한다. 완성된 이미지를 Kubernetes Pod에 배포하기 위한 빌드 서버 구성을 다루며, WAS 서비스 실행은 포함하지 않는다.
1. 외부망에서 가져와야 하는 파일
반입 자료는 크게 Docker 설치용 RPM과 Java 21 베이스 이미지 TAR로 구분한다. RPM은 서버에 Docker를 설치하는 데 사용하고, 이미지 TAR는 Docker 안에서 사용할 Java 환경을 준비하는 데 사용한다.
| 준비 항목 | 파일 예시 | 용도 |
|---|---|---|
| Docker RPM | docker-버전.x86_64.rpm |
Docker 명령어와 데몬 설치 |
| containerd RPM | containerd-버전.x86_64.rpm |
Docker가 사용하는 컨테이너 수명 주기 관리 구성요소 |
| runc RPM | runc-버전.x86_64.rpm |
컨테이너 프로세스를 실행하는 저수준 런타임 |
| Buildx RPM | docker-buildx-버전.x86_64.rpm |
BuildKit 기반 이미지 빌드용 CLI 플러그인 |
| 추가 의존성 RPM | 패키지 관리자가 요구하는 라이브러리·도구 RPM | 대상 서버에 없는 의존성 충족 |
| Java 21 이미지 | temurin21-jdk-jammy-amd64.tar |
Java 21 기반 Docker 이미지 빌드 |
| 검증 자료 | SHA256SUMS, 패키지 목록, 이미지 정보 |
반입 파일 무결성과 버전 확인 |
실제 설치 중 containerd RPM이 없어 외부망에서 추가로 가져오는 상황이 발생할 수 있다. runc가 설치되어 있어도 containerd를 대신할 수 없으므로 두 항목을 각각 확인해야 한다.
위 목록은 핵심 구성요소다. 필요한 전체 RPM 수량은 대상 서버의 기존 설치 패키지와 선택한 Docker 버전에 따라 달라진다.
2. 내부 서버의 OS와 기존 패키지 확인
외부망 준비 서버는 내부 서버와 배포판, 서비스 팩, CPU 아키텍처, 저장소 구성과 패치 수준을 최대한 맞춘다. SLES용 패키지와 다른 배포판용 패키지를 임의로 섞지 않는다.
# 폐쇄망 대상 서버에서 실행
cat /etc/os-release
uname -m
# 설치 여부 확인: 미설치 항목은 not installed로 표시될 수 있음
rpm -q docker containerd runc docker-buildx
# 전체 설치 패키지 목록 기록
rpm -qa | sort > /tmp/target-installed-packages.txt
uname -m이 x86_64이면 Docker 이미지 플랫폼은 일반적으로 linux/amd64를 선택한다. ARM 서버라면 RPM과 베이스 이미지 모두 해당 아키텍처로 준비해야 한다.
3. 외부망에서 Docker RPM 준비하기
3-1. SUSE 저장소 확인
정상 등록된 외부망 SLES 서버에서 저장소를 확인한다. Docker 패키지를 제공하는 Containers 모듈과 필요한 의존성 저장소에 접근할 수 있어야 한다.
# 외부망 준비 서버에서 실행
SUSEConnect --status-text
zypper lr -u
zypper refresh
# 패키지와 제공 버전 확인
zypper search -s -t package docker containerd runc docker-buildx
패키지가 조회되지 않는다면 먼저 SUSE 등록 상태와 모듈 활성화 여부를 확인한다. 다른 서비스 팩이나 다른 배포판의 저장소를 무작정 추가하는 방식은 피한다.
3-2. 설치하지 않고 RPM 다운로드
내부 서버와 유사하게 구성하고 Docker를 아직 설치하지 않은 준비용 VM에서 다음 명령을 실행한다.
mkdir -p /srv/offline-docker/rpms
mkdir -p /srv/offline-docker/cache
mkdir -p /srv/offline-docker/images
# Docker와 핵심 구성요소 및 필요한 의존성 다운로드
zypper --pkg-cache-dir /srv/offline-docker/cache \
install --download-only docker containerd runc docker-buildx
# 하위 캐시 디렉터리에 저장된 RPM을 반입 폴더로 복사
find /srv/offline-docker/cache -type f -name '*.rpm' \
-exec cp -t /srv/offline-docker/rpms/ {} +
# 준비된 파일 확인
ls -lh /srv/offline-docker/rpms/
--download-only는 현재 서버의 패키지 상태를 기준으로 설치 트랜잭션을 계산한다. 외부망 준비 서버에서 다운로드가 끝났다는 사실만으로 내부 서버의 의존성이 모두 준비되었다고 판단하면 안 된다.
가장 확실한 방법은 내부 서버와 유사한 검증용 VM에서 외부 저장소 접근을 차단한 상태로 실제 설치를 확인하는 것이다. Docker가 이미 설치된 외부 서버라면 별도 준비용 VM을 사용하는 편이 누락을 줄이기 쉽다.
3-3. 패키지 목록과 서명 확인
cd /srv/offline-docker
rpm -qp --qf '%{NAME} %{VERSION}-%{RELEASE} %{ARCH}\n' \
rpms/*.rpm | sort > rpm-manifest.txt
cat rpm-manifest.txt
# 특히 누락하기 쉬운 핵심 패키지 확인
grep -E '^(docker|containerd|runc|docker-buildx) ' rpm-manifest.txt
# RPM 서명 확인
rpm -K rpms/*.rpm
서명 확인에 필요한 공식 SUSE 공개 키도 대상 서버에 준비되어 있어야 한다. NOKEY가 나오면 신뢰할 수 있는 경로로 확보한 공식 키를 확인하며, 서명 검증을 끄는 방식으로 해결하지 않는다.
4. 외부망에서 Java 21 베이스 이미지 준비하기
Docker 설치 RPM만 반입하면 Java 이미지는 생기지 않는다. 외부망의 Docker 사용 가능 서버에서 Java 21 이미지를 내려받아 TAR 파일로 저장해야 한다.
예제에서는 eclipse-temurin:21-jdk-jammy를 사용한다. Java 21 JDK와 Ubuntu 22.04 계열 사용자 공간을 포함한 이미지이며, 호스트가 SUSE라고 해서 컨테이너 이미지도 반드시 SUSE여야 하는 것은 아니다. 다만 조직의 지원 정책과 애플리케이션 호환성은 확인해야 한다.
# 외부망 Docker 서버에서 실행
mkdir -p /srv/offline-docker/images
docker pull --platform=linux/amd64 eclipse-temurin:21-jdk-jammy
# 이미지 플랫폼과 식별 정보 기록
docker image inspect eclipse-temurin:21-jdk-jammy \
--format '{{.Os}}/{{.Architecture}}'
docker image inspect eclipse-temurin:21-jdk-jammy \
> /srv/offline-docker/images/temurin21-inspect.json
# 폐쇄망 반입용 TAR 생성
docker save \
-o /srv/offline-docker/images/temurin21-jdk-jammy-amd64.tar \
eclipse-temurin:21-jdk-jammy
21-jdk-jammy는 Java 21 계열을 선택하지만, 시간이 지나면 가리키는 이미지가 바뀔 수 있다. 운영에서는 반입한 TAR, 이미지 ID와 원본 RepoDigest를 함께 기록한다. 정확한 패치 버전을 고정하려면 공식 태그 목록에서 제공 여부를 확인한 뒤 해당 태그로 내려받는다.
4-1. 반입 자료 체크섬 생성
RPM과 이미지 TAR를 한 폴더에 모은 뒤 체크섬을 만든다. RPM 준비 서버와 이미지 준비 서버가 다르다면 파일을 모은 최종 위치에서 실행한다.
cd /srv/offline-docker
sha256sum rpms/*.rpm images/*.tar > SHA256SUMS
ls -lh
ls -lh images/
rpms, images, rpm-manifest.txt, SHA256SUMS를 승인된 반입 절차로 내부 서버에 전달한다.
5. 폐쇄망 서버에 Docker 설치하기
반입 자료를 내부 서버의 /opt/offline-docker에 배치했다고 가정한다. 아래 명령은 root 권한으로 실행한다.
5-1. 무결성과 의존성 사전 확인
cd /opt/offline-docker
# 모든 항목이 OK인지 확인
sha256sum -c SHA256SUMS
# RPM 서명 확인
rpm -K rpms/*.rpm
# 등록된 원격 저장소를 사용하지 않고 설치 가능 여부 확인
zypper --disable-repositories install --dry-run \
/opt/offline-docker/rpms/*.rpm
의존성 오류가 없고 설치 계획이 적절한지 확인한 뒤 실제 설치를 진행한다. --disable-repositories는 해당 명령에서 저장소를 사용하지 않도록 하며, 기존 저장소 설정을 영구 변경하지 않는다.
5-2. RPM 설치와 Docker 시작
zypper --disable-repositories install \
/opt/offline-docker/rpms/*.rpm
systemctl enable --now docker
# 설치 및 서비스 확인
rpm -q docker containerd runc docker-buildx
systemctl is-active docker
docker version
docker info
docker buildx version
docker version에서 Client와 Server 정보가 모두 나오면 CLI가 Docker 데몬에 연결된 상태다. Client 정보만 보인다면 Docker 서비스 상태와 접속 권한을 확인한다.
# Docker가 시작되지 않을 때 확인
systemctl status docker --no-pager
journalctl -u docker -n 100 --no-pager
설치 직후 hello-world를 실행하면 해당 이미지가 없어 외부 다운로드를 시도할 수 있다. 폐쇄망에서는 우선 위 명령으로 설치 상태를 확인하고, 반입한 이미지로 다음 단계를 진행한다.
6. containerd RPM이 없을 때 해결 방법
설치 과정에서 containerd 관련 의존성 오류가 발생하면 먼저 설치 여부와 반입 파일을 각각 확인한다.
# 대상 서버 설치 상태
rpm -q containerd runc
# 반입된 RPM의 실제 패키지 이름 확인
rpm -qp --qf '%{NAME} %{VERSION}-%{RELEASE} %{ARCH}\n' \
/opt/offline-docker/rpms/*.rpm | sort
# Docker RPM이 요구하는 의존성 확인
rpm -qpR /opt/offline-docker/rpms/docker-*.rpm
runc만 설치되어 있고 containerd가 없다면 containerd RPM을 별도로 준비해야 한다. 외부망에서 동일한 SLES 저장소의 호환 버전을 확보하고, 추가 의존성도 함께 반입한다.
# 외부망 준비 서버에서 실행
zypper --pkg-cache-dir /srv/offline-docker/cache \
install --download-only containerd
외부망 서버에 containerd가 이미 설치되어 있다면 위 명령이 RPM을 다시 받지 않을 수 있다. 이때는 미설치 준비용 VM 또는 해당 공식 저장소의 패키지 다운로드 기능을 사용해 필요한 RPM을 확보한다.
추가 RPM을 반입한 후에는 containerd 하나만 강제 설치하지 말고, 전체 RPM을 대상으로 의존성 검사를 다시 수행한다.
# 폐쇄망 대상 서버에서 실행
zypper --disable-repositories install --dry-run \
/opt/offline-docker/rpms/*.rpm
# 사전 확인이 통과한 경우 설치
zypper --disable-repositories install \
/opt/offline-docker/rpms/*.rpm
이 글의 SUSE 패키지 경로는 docker, containerd, runc를 사용한다. 다른 배포판의 Docker CE 설치 글에 나오는 docker-ce나 containerd.io를 그대로 섞어 설치하면 의존성과 파일 충돌이 생길 수 있다.
rpm --nodeps로 의존성을 무시하면 설치 기록만 생성되고 Docker는 정상 동작하지 않을 수 있다.
7. 폐쇄망에서 Java 21 이미지 불러오기
docker load \
-i /opt/offline-docker/images/temurin21-jdk-jammy-amd64.tar
docker image ls eclipse-temurin
docker image inspect eclipse-temurin:21-jdk-jammy \
--format '{{.Os}}/{{.Architecture}}'
이 과정은 Java 21 베이스 이미지를 로컬 Docker 이미지 저장소에 등록한다. TAR를 일반 파일처럼 압축 해제하거나 docker import로 가져오지 않고, docker save와 짝이 되는 docker load를 사용한다.
7-1. 호스트 Java와 이미지 Java의 차이
| 구분 | 설정 기준 |
|---|---|
| 호스트 Java | SUSE 서버에 설치된 JDK와 호스트의 JAVA_HOME |
| 이미지 Java | Dockerfile의 FROM으로 선택한 이미지에 포함된 JDK |
| 이번 예제 | Temurin Java 21 이미지를 기반으로 구성 |
호스트의 기본 Java를 21로 설정했다고 해서 이미지 안의 Java도 자동으로 21이 되는 것은 아니다. 반대로 호스트에 JDK가 없어도 Java 21 베이스 이미지를 사용한 빌드는 가능하다.
8. Java 21 공통 베이스 이미지 빌드하기
반입한 Temurin 이미지를 그대로 사용할 수도 있다. 여러 WAS 이미지에서 사용할 공통 이름과 기본 작업 경로를 정하려면 다음과 같이 내부용 베이스 이미지를 만든다.
mkdir -p /opt/image-build/java21-base
cd /opt/image-build/java21-base
cat > Dockerfile <<'EOF'
FROM eclipse-temurin:21-jdk-jammy
WORKDIR /opt/app
CMD ["java", "-version"]
EOF
이 Dockerfile은 이미 Java 21이 포함된 이미지를 사용하므로 JDK 설치 명령이 필요 없다. 기본 Java 환경 변수도 원본 이미지의 설정을 사용한다.
8-1. 기본 Docker 빌더 확인
docker buildx ls
# 기본 Docker 컨텍스트의 빌더 선택
docker buildx use default
선택된 빌더의 드라이버가 docker인지 확인한다. 이 드라이버는 Docker Engine에 포함된 BuildKit을 사용하며 로컬 이미지 저장소를 활용한다. 별도의 docker-container 빌더는 BuildKit 이미지 반입과 별도 캐시 준비가 추가로 필요할 수 있다.
8-2. 외부 패키지 다운로드 없이 빌드
cd /opt/image-build/java21-base
docker build \
--pull=false \
--network=none \
-t internal/java21-base:1.0 \
.
--pull=false: 베이스 이미지의 최신 버전을 강제로 Pull하지 않는다.--network=none: 빌드 중 RUN 명령의 네트워크 사용을 막는다.-t: 완성 이미지의 이름과 태그를 지정한다.- 마지막
.: 현재 디렉터리를 빌드 컨텍스트로 사용한다.
--network=none은 RUN 단계에 적용된다. 베이스 이미지가 로컬에 없거나 별도 Dockerfile 프런트엔드를 지정하면 이미지 조회나 다운로드가 발생할 수 있다.
이번 예제는 미리 로드한 베이스 이미지와 기본 docker 드라이버를 사용하고, 외부 프런트엔드를 가져오는 syntax 지시문을 넣지 않는다. FROM 이름과 로드된 이미지 태그도 정확히 일치해야 한다.
9. 빌드 후 이미지 확인하기
다음 명령은 WAS를 실행하지 않고 이미지의 생성 여부와 설정을 확인한다.
docker image ls internal/java21-base
docker image inspect internal/java21-base:1.0 \
--format 'ID={{.Id}} OS={{.Os}} ARCH={{.Architecture}}'
docker image inspect internal/java21-base:1.0 \
--format '{{json .Config.Env}}'
docker image inspect internal/java21-base:1.0 \
--format '{{json .Config.Cmd}}'
docker image history internal/java21-base:1.0
위 검사는 이미지 메타데이터와 빌드 이력을 확인한다. 실제 Java 실행까지 검증하려면 별도의 일회성 검사가 필요하다. 아래 명령은 선택 사항이며, WAS 대신 Java 버전만 출력하고 컨테이너를 삭제한다.
# 선택: Java 21 실행 여부 확인
docker run --rm --pull=never --network=none \
--entrypoint java \
internal/java21-base:1.0 -version
출력에서 21 계열 버전이 확인되면 Java 21 실행 환경을 검증한 것이다. 이 결과가 WildFly나 업무 애플리케이션의 정상 동작까지 보장하지는 않는다.
10. 이후 WildFly 이미지에 적용하는 방법
이후 WildFly 이미지의 Dockerfile에서는 다음처럼 공통 베이스를 지정할 수 있다.
FROM internal/java21-base:1.0
여기에 Java 21을 지원하는 WildFly 배포본과 애플리케이션을 추가한다. 기존 WildFly 폴더를 복사하는 것만으로 Java 21 호환성이 확보되지는 않는다. WildFly 버전, JDBC 드라이버, JVM 옵션, 네이티브 라이브러리와 업무 애플리케이션의 호환성을 확인해야 한다.
폐쇄망 빌드에서는 Dockerfile에 apt-get, zypper, curl 등을 넣더라도 외부 저장소에 접근할 수 없다. 필요한 패키지와 파일은 사전에 준비하거나 승인된 내부 저장소를 사용한다.
또한 Docker 서버에서 만든 로컬 이미지는 Kubernetes 노드에 자동으로 전달되지 않는다. 완성된 WAS 이미지는 내부 Harbor 등에 업로드하고, Pod가 해당 레지스트리에서 가져오도록 구성한다.
11. 설치·빌드 전 최종 확인 목록
- 외부망과 내부망의 SLES 서비스 팩 및 CPU 아키텍처가 일치하는가?
- Docker, containerd, runc RPM과 추가 의존성을 준비했는가?
- 빌드에 필요한 docker-buildx를 준비했는가?
- 외부망 서버에 이미 설치되어 다운로드에서 빠진 패키지가 없는가?
- 외부 저장소 없이 설치 가능한지 검증했는가?
- Java 21 베이스 이미지를 올바른 플랫폼으로 저장했는가?
- 반입 파일의 체크섬과 RPM 서명을 확인했는가?
- docker load 후 FROM에 사용할 태그가 존재하는가?
- 선택한 빌더가 docker 드라이버를 사용하는가?
- 완성 이미지를 전달할 내부 레지스트리 경로가 준비되어 있는가?
참고 문서
'지식 공유 > ETC' 카테고리의 다른 글
| WildFly WAR 배포가 진행되지 않을 때: dodeploy와 deployed 파일 구분 및 점검 방법 (0) | 2026.10.21 |
|---|---|
| 2027년 상반기 보안 엔지니어 자격증 준비 기본편: 종류·난이도·시험 일정 (0) | 2026.10.21 |
| 유라클 Athena Code Assistant 상세 설명|Qwen·vLLM·bge-m3·L40 구성과 장단점 (0) | 2026.10.20 |
| DRM과 SSO, APIM이 필요한 이유: 문서·인증·API 보안의 역할 (0) | 2026.10.01 |
| Docker 이미지 최적화하기: 용량 줄이기부터 멀티 스테이지 빌드까지 (0) | 2026.10.01 |
