1. Containerd 및 CNI 플러그인 설치 (바이너리 방식)
컨테이너 런타임 환경을 구축하기 위해 containerd와 CNI(Container Network Interface) 플러그인을 바이너리 파일로 직접 설치합니다.
1.1 containerd 바이너리 및 서비스 파일 준비
# containerd 바이너리 다운로드
root@ubuntu-node:~# wget https://github.com/containerd/containerd/releases/download/v1.7.2/containerd-1.7.2-linux-amd64.tar.gz
# 압축 해제 및 바이너리 복사
root@ubuntu-node:~# tar xvf containerd-1.7.2-linux-amd64.tar.gz -C /usr/local/
root@ubuntu-node:~# cp /usr/local/bin/* /usr/local/bin/
# 설치 확인
root@ubuntu-node:~# containerd -v
containerd github.com/containerd/containerd v1.7.2
# systemd 서비스 파일 생성
root@ubuntu-node:~# cat <<EOF | sudo tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
1.2 containerd 환경 설정
# 기본 설정 파일 생성
root@ubuntu-node:~# mkdir -p /etc/containerd
root@ubuntu-node:~# containerd config default > /etc/containerd/config.toml
# 설정 파일 수정 (sandbox 이미지 및 미러 레포지토리)
root@ubuntu-node:~# sed -i 's|sandbox_image = ".*"|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml
root@ubuntu-node:~# sed -i '/\[plugins\."io.containerd.grpc.v1.cri".registry.mirrors\]/a\ \ [plugins\."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n\ \ endpoint = ["https://frncu3gx.mirror.aliyuncs.com"]' /etc/containerd/config.toml
# 서비스 시작 및 활성화
root@ubuntu-node:~# systemctl daemon-reload
root@ubuntu-node:~# systemctl start containerd
root@ubuntu-node:~# systemctl enable containerd
root@ubuntu-node:~# systemctl status containerd
1.3 runc 설치
root@ubuntu-node:~# wget -O runc https://github.com/opencontainers/runc/releases/download/v1.1.8/runc.amd64
root@ubuntu-node:~# chmod +x runc
root@ubuntu-node:~# mv runc /usr/local/bin/runc
root@ubuntu-node:~# runc -v
runc version 1.1.8
1.4 CNI 플러그인 설치
root@ubuntu-node:~# wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
root@ubuntu-node:~# mkdir -p /opt/cni/bin
root@ubuntu-node:~# tar xvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin/
2. nerdctl을 이용한 컨테이너 관리
2.1 nerdctl 설치 및 설정
root@ubuntu-node:~# wget https://github.com/containerd/nerdctl/releases/download/v1.4.0/nerdctl-1.4.0-linux-amd64.tar.gz
root@ubuntu-node:~# tar xvf nerdctl-1.4.0-linux-amd64.tar.gz -C /usr/local/bin/
# nerdctl 설정 파일 생성
root@ubuntu-node:~# mkdir -p /etc/nerdctl
root@ubuntu-node:~# cat <<EOF | sudo tee /etc/nerdctl/nerdctl.toml
namespace = "k8s.io"
debug = false
debug_full = false
insecure_registry = true
EOF
2.2 nerdctl 기본 명령어
# Nginx 컨테이너 실행
root@ubuntu-node:~# nerdctl run -d --name web-nginx -p 8080:80 nginx:latest
# 실행 중인 컨테이너 확인
root@ubuntu-node:~# nerdctl ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c8f1e37a23b4 docker.io/library/nginx:latest "/docker-entrypoint.…" 15 seconds ago Up 0.0.0.0:8080->80/tcp web-nginx
# 컨테이너 내부 접속
root@ubuntu-node:~# nerdctl exec -it c8f1e37a23b4 bash
root@c8f1e37a23b4:/# hostname -I
10.4.0.2
root@c8f1e37a23b4:/# curl -I www.baidu.com
HTTP/1.1 200 OK
# 컨테이너 중지 및 삭제
root@ubuntu-node:~# nerdctl stop web-nginx
root@ubuntu-node:~# nerdctl rm web-nginx
# 이미지 목록 확인
root@ubuntu-node:~# nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
nginx latest 08bc36ad5247 2 hours ago linux/amd64 192.1 MiB 67.3 MiB
3. HTTPS 기반 Harbor 레지스트리 구축
3.1 사전 준비: 인증서 파일
미리 발급받은 SSL 인증서를 서버에 업로드합니다.
root@harbor-node:~# mkdir -p /data/certfile /data/privatekey
root@harbor-node:~# ls -l /data/certfile/ /data/privatekey/
/data/certfile:
total 4
-rw-r--r-- 1 root root 1675 Jul 25 10:00 yourdomain.pem
/data/privatekey:
total 4
-rw-r--r-- 1 root root 1675 Jul 25 10:00 yourdomain.key
3.2 Harbor 설치
root@harbor-node:~# wget https://github.com/goharbor/harbor/releases/download/v2.8.2/harbor-offline-installer-v2.8.2.tgz
root@harbor-node:~# tar xvf harbor-offline-installer-v2.8.2.tgz -C /opt/
root@harbor-node:~# cd /opt/harbor
root@harbor-node:/opt/harbor# cp harbor.yml.tmpl harbor.yml
# 설정 파일 수정
root@harbor-node:/opt/harbor# vim harbor.yml
# hostname: yourdomain.com
# https:
# port: 443
# certificate: /data/certfile/yourdomain.pem
# private_key: /data/privatekey/yourdomain.key
# harbor_admin_password: YourSecurePassword
# data_volume: /data/harbor
# 설치 실행 (보안 스캐너 Trivy 포함)
root@harbor-node:/opt/harbor# ./install.sh --with-trivy
# 설치 로그 마지막 부분
✔ ----Harbor has been installed and started successfully.----
3.3 DNS 설정
클라이언트 호스트 파일에 도메인을 추가합니다.
root@client-node:~# echo "192.168.1.100 yourdomain.com" >> /etc/hosts
3.4 nerdctl을 이용한 이미지 Push/Pull
# Harbor 로그인
root@client-node:~# nerdctl login yourdomain.com
Username: admin
Password:
Login Succeeded
# 이미지 태그 및 Push
root@client-node:~# nerdctl tag nginx:latest yourdomain.com/library/nginx:latest
root@client-node:~# nerdctl push yourdomain.com/library/nginx:latest
# 이미지 Pull
root@client-node:~# nerdctl pull yourdomain.com/library/nginx:latest
4. 멀티 스테이지를 활용한 Nginx 이미지 빌드
4.1 Ubuntu 기반 Nginx 이미지 Dockerfile
root@build-node:~/ubuntu-nginx# cat <<'EOF' > Dockerfile
# 1단계: 빌드 스테이지
FROM ubuntu:22.04 AS builder
RUN apt update && apt install -y \
wget \
gcc \
libpcre3-dev \
zlib1g-dev \
make
# Nginx 소스 다운로드 및 컴파일
RUN wget http://nginx.org/download/nginx-1.18.0.tar.gz && \
tar xzf nginx-1.18.0.tar.gz && \
cd nginx-1.18.0 && \
./configure --prefix=/opt/nginx --user=nginx --group=nginx && \
make && make install
# 2단계: 실행 스테이지
FROM ubuntu:22.04 AS runtime
# 런타임 의존성 설치
RUN apt update && apt install -y \
iproute2 \
tcpdump \
curl \
vim \
iputils-ping
# 빌드 스테이지에서 nginx 실행 파일 복사
COPY --from=builder /opt/nginx /opt/nginx
# 사용자 생성 및 설정
RUN useradd -r -s /sbin/nologin nginx && \
chown -R nginx:nginx /opt/nginx
# 설정 및 정적 파일 추가
COPY nginx.conf /opt/nginx/conf/
COPY index.html /opt/nginx/html/
EXPOSE 80
CMD ["/opt/nginx/sbin/nginx", "-g", "daemon off;"]
EOF
# 이미지 빌드
root@build-node:~/ubuntu-nginx# docker build -t yourdomain.com/library/nginx:ubuntu-v1 .
4.2 Alpine 기반 Nginx 이미지 Dockerfile
root@build-node:~/alpine-nginx# cat <<'EOF' > Dockerfile
FROM alpine:3.18 AS builder
RUN apk add --no-cache \
build-base \
pcre-dev \
zlib-dev \
openssl-dev
RUN wget http://nginx.org/download/nginx-1.18.0.tar.gz && \
tar xzf nginx-1.18.0.tar.gz && \
cd nginx-1.18.0 && \
./configure --prefix=/opt/nginx --user=nginx --group=nginx && \
make && make install
FROM alpine:3.18 AS runtime
RUN addgroup -S nginx && adduser -S -G nginx nginx
COPY --from=builder /opt/nginx /opt/nginx
COPY nginx.conf /opt/nginx/conf/
COPY index.html /opt/nginx/html/
EXPOSE 80
CMD ["/opt/nginx/sbin/nginx", "-g", "daemon off;"]
EOF
# 이미지 빌드
root@build-node:~/alpine-nginx# docker build -t yourdomain.com/library/nginx:alpine-v1 .
5. Docker Compose를 활용한 다중 컨테이너 애플리케이션
5.1 Docker Compose 설치
root@app-node:~# curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
root@app-node:~# chmod +x /usr/local/bin/docker-compose
root@app-node:~# docker-compose --version
Docker Compose version v2.23.0
5.2 docker-compose.yml 작성
root@app-node:~/myapp# cat <<'EOF' > docker-compose.yml
version: '3.8'
services:
nginx-proxy:
image: nginx:1.25-alpine
container_name: web-proxy
ports:
- "80:80"
- "443:443"
networks:
- frontend
- backend
depends_on:
- tomcat-app
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
tomcat-app:
image: yourdomain.com/library/tomcat-myapp:v1
container_name: app-server
networks:
- backend
depends_on:
- mysql-db
mysql-db:
image: mysql:8.0
container_name: database
environment:
MYSQL_ROOT_PASSWORD: MySecretPass
TZ: Asia/Seoul
volumes:
- mysql_data:/var/lib/mysql
networks:
- backend
volumes:
mysql_data:
networks:
frontend:
driver: bridge
backend:
driver: bridge
EOF
# Nginx 설정 파일
root@app-node:~/myapp# mkdir nginx
root@app-node:~/myapp# cat <<'EOF' > nginx/default.conf
server {
listen 80;
server_name localhost;
location /myapp {
proxy_pass http://tomcat-app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
EOF
5.3 애플리케이션 실행
root@app-node:~/myapp# docker-compose up -d
# 실행 상태 확인
root@app-node:~/myapp# docker-compose ps
NAME IMAGE COMMAND SERVICE STATUS PORTS
web-proxy nginx:1.25-alpine "/docker-entrypoint.…" nginx-proxy running 0.0.0.0:80->80/tcp
app-server tomcat-myapp:v1 "/apps/tomcat/bin/do…" tomcat-app running 8080/tcp
database mysql:8.0 "docker-entrypoint.s…" mysql-db running 3306/tcp