Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
# 변경한 사람: 이소은
# tensorflow version 2.13.0-gpu -> 2.18.0-gpu

##### decs:260501#####
# 변경한 사람: 임준영
# Xfce, TigerVNC, noVNC 기반 GUI 접속 지원 추가

########################### version history end ##########################

# TensorFlow 2.18.0 GPU 공식 이미지 사용 (CUDA 12.3, cuDNN 8.9 포함, Ubuntu 22.04 기반)
Expand All @@ -30,6 +34,13 @@ vim \
wget \
curl \
ssh \
dbus-x11 \
xfce4 \
xfce4-terminal \
tigervnc-standalone-server \
tigervnc-common \
novnc \
websockify \
software-properties-common

# motd install
Expand Down Expand Up @@ -78,6 +89,9 @@ RUN mkdir /jupyter_config \
# entrypoint.sh 복사
COPY entrypoint.sh /

# noVNC 접속 포트. VNC 서버(5901)는 localhost에만 바인딩합니다.
EXPOSE 6080

# SSHD 서버를 실행하고, entrypoint 파일을 start/restart 시 마다 실행, dev/null에 entrypoint 로그를 저장
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["bash", "/entrypoint.sh"]
47 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@

| 이미지 태그 (Image Tag) | TensorFlow 버전 | CUDA / cuDNN | 베이스 OS (Base OS) | 주요 변경사항 및 설명 |
| :--- | :--- | :--- | :--- | :--- |
| `dguailab/decs:latest`<br>`dguailab/decs:260201` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | **(최신)** 의도되지 않은 MOTD 출력 방지 버그 수정 |
| `dguailab/decs:251023` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | **(이전 안정 버전)** Jupyter Notebook 버전 변경으로 인한 오류 해결 버전 |
| `dguailab/decs:251002` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | TensorFlow 2.18.0 업그레이드, 최신 GPU 환경 지원 |
| `dguailab/decs:250926` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | **(이전 안정 버전)** TensorFlow 2.13.0 기반의 안정화 버전 |
| `dguailab/decs:latest`<br>`dguailab/decs:260501` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | **(최신)** Xfce + TigerVNC + noVNC 기반 브라우저 GUI 접속 지원 추가 |
| `dguailab/decs:260427` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | 기존 사용자 컨테이너 변경 시 `~/.bashrc`의 conda initialize 블록 갱신, 경고 주석 영문화 및 인덴트 수정 |
| `dguailab/decs:260403` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | 계정/권한 검증 강화, config-server 주입 기반 sudo 권한 축소, Jupyter 및 컨테이너 유지 프로세스 비-root 실행, gosu 추가 |
| `dguailab/decs:260201` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | 의도되지 않은 MOTD 출력 방지 버그 수정 |
| `dguailab/decs:251023` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | **(이전 안정 버전)** Jupyter Notebook 설정 파일 생성/경로 오류 해결, 랜덤 토큰 저장 방식 반영 |
| `dguailab/decs:251002` | **2.18.0** | CUDA 12.5<br>cuDNN 8.9 | Ubuntu 22.04 | TensorFlow 2.18.0 업그레이드, 최신 GPU 환경 지원, Docker Hub 자동 빌드/푸시 워크플로 도입 |
| `dguailab/decs:250926` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | **(이전 안정 버전)** 사용자 홈 디렉토리 소유권 설정 순서 수정, 이슈/PR 템플릿 추가 |
| `dguailab/decs:250428` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | Jupyter Lab 설정 파일을 사용자 홈의 `.jupyter` 경로에서 생성하고 사용하도록 수정 |
| `dguailab/decs:250416` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | Jupyter Notebook 설정 파일 생성 로직 수정, 10자리 랜덤 토큰 생성 및 파일 저장 추가 |
| `dguailab/decs:250323` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | `useradd` 옵션 보완, MOTD 공지 추가, TensorFlow ASCII 출력 제거 |
| `dguailab/decs:250309` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | ldconfig permission denied 오류 방지, MOTD/Slack 공지 반영, Conda 최신화 반영 |
| `dguailab/decs:250218` | **2.13.0** | CUDA 11.8<br>cuDNN 8.6 | Ubuntu 20.04 | Anaconda3 2024.10-1 설치로 Conda 24.9.2 업그레이드 |

## ⚙️ 사용 방법
필요한 버전의 이미지를 Docker Hub에서 pull 받아 사용합니다.
Expand All @@ -28,6 +36,37 @@ docker pull dguailab/decs:251002
docker pull dguailab/decs:250926
```

### GUI 접속(noVNC)
`260501` 버전부터 브라우저 기반 GUI 접속을 지원합니다. GUI 접속은 기본 비활성화 상태이며, 컨테이너 생성 시 `ENABLE_VNC=true` 환경변수를 전달한 경우에만 시작됩니다.

- 컨테이너 내부 noVNC 포트: `6080`
- 컨테이너 내부 VNC 포트: `localhost:5901` 전용
- 접속 URL: `http://서버주소:외부포트/vnc.html`
- VNC 비밀번호 저장 위치: `/home/$USER_ID/decs_jupyter_lab/vnc_password.txt`

직접 `docker run`을 사용할 때는 다음처럼 환경변수와 포트를 함께 지정합니다.

```
-e ENABLE_VNC=true -p 외부포트:6080
```

운영 스크립트(`~/uid`)에서는 `--enable_vnc true`를 주면 컨테이너 내부 `6080` 포트를 자동으로 추가하고, Docker 실행 환경변수에 `ENABLE_VNC=true`를 함께 전달합니다. FARM2 예시는 외부 포트 범위 `9100~9199` 중 하나가 `6080`에 연결되는 방식입니다.

```
--enable_vnc true
```

관련 환경변수:

| 환경변수 | 기본값 | 설명 |
| :--- | :--- | :--- |
| `ENABLE_VNC` | `false` | `true`로 설정한 경우에만 VNC/noVNC를 시작합니다. |
| `VNC_PASSWORD` | 랜덤 8자리 | 지정하지 않으면 자동 생성 후 `vnc_password.txt`에 저장합니다. |
| `VNC_RESOLUTION` | `1920x1080` | VNC 화면 해상도입니다. |
| `VNC_DEPTH` | `24` | VNC 색상 깊이입니다. |
| `VNC_DISPLAY` | `1` | VNC display 번호입니다. 기본 VNC 포트는 `5901`입니다. |
| `NOVNC_PORT` | `6080` | noVNC가 컨테이너 내부에서 listen할 포트입니다. |


# ⚒️ 빌드 자동화
이 Docker 이미지는 GitHub Actions를 통해 자동으로 빌드 및 배포됩니다.
Expand Down
87 changes: 87 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,89 @@
#!/bin/bash

start_novnc() {
case "${ENABLE_VNC:-false}" in
true|TRUE|1|yes|YES|on|ON) ;;
*)
echo "VNC/noVNC disabled. Set ENABLE_VNC=true to enable it."
return 0
;;
esac

local user_home="/home/$USER_ID"
local vnc_dir="$user_home/.vnc"
local vnc_display="${VNC_DISPLAY:-1}"
local vnc_resolution="${VNC_RESOLUTION:-1920x1080}"
local vnc_depth="${VNC_DEPTH:-24}"
local novnc_port="${NOVNC_PORT:-6080}"
local vnc_password_file="$user_home/decs_jupyter_lab/vnc_password.txt"
local vnc_password

vnc_display="${vnc_display#:}"
if ! [[ "$vnc_display" =~ ^[0-9]+$ && "$novnc_port" =~ ^[0-9]+$ && "$vnc_depth" =~ ^[0-9]+$ ]]; then
echo "Invalid VNC configuration. Check VNC_DISPLAY, NOVNC_PORT, and VNC_DEPTH."
return 1
fi
local vnc_port=$((5900 + vnc_display))

if ! command -v vncserver >/dev/null 2>&1 || ! command -v websockify >/dev/null 2>&1; then
echo "VNC/noVNC packages are not installed. Skipping GUI startup."
return 0
fi

mkdir -p "$vnc_dir" "$user_home/decs_jupyter_lab" /tmp/.X11-unix /tmp/.ICE-unix
chown root:root /tmp/.X11-unix /tmp/.ICE-unix
chmod 1777 /tmp/.X11-unix /tmp/.ICE-unix

if [[ -n "${VNC_PASSWORD:-}" ]]; then
vnc_password="$VNC_PASSWORD"
elif [[ -s "$vnc_password_file" ]]; then
vnc_password=$(tr -d '\r\n' < "$vnc_password_file" | head -c 8)
else
vnc_password=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 8)
fi
vnc_password="${vnc_password:0:8}"

if [[ -z "$vnc_password" ]]; then
echo "Failed to prepare VNC password. Skipping GUI startup."
return 1
fi

printf "%s\n" "$vnc_password" > "$vnc_password_file"
chmod 600 "$vnc_password_file"

printf "%s\n" "$vnc_password" | vncpasswd -f > "$vnc_dir/passwd"
chmod 600 "$vnc_dir/passwd"

cat > "$vnc_dir/xstartup" <<'EOF'
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
export XDG_SESSION_TYPE=x11
export XKL_XMODMAP_DISABLE=1
xrdb "$HOME/.Xresources" 2>/dev/null || true
exec dbus-launch --exit-with-session startxfce4
EOF
chmod +x "$vnc_dir/xstartup"
chown -R "$USER_ID:$USER_GROUP" "$vnc_dir" "$vnc_password_file"

sudo -u "$USER_ID" env HOME="$user_home" USER="$USER_ID" \
vncserver -kill ":$vnc_display" >/tmp/vnc-kill.log 2>&1 || true

echo "trying TigerVNC on localhost:$vnc_port..."
if ! sudo -u "$USER_ID" env HOME="$user_home" USER="$USER_ID" \
vncserver -localhost yes ":$vnc_display" -geometry "$vnc_resolution" -depth "$vnc_depth" >/tmp/vncserver.log 2>&1; then
echo "TigerVNC startup failed. See /tmp/vncserver.log."
cat /tmp/vncserver.log
return 1
fi
echo "TigerVNC listening on localhost:$vnc_port"

pkill -f "websockify.*$novnc_port" >/dev/null 2>&1 || true
echo "trying noVNC on 0.0.0.0:$novnc_port..."
nohup websockify --web=/usr/share/novnc "0.0.0.0:$novnc_port" "localhost:$vnc_port" >/tmp/novnc.log 2>&1 &
echo "noVNC listening on port $novnc_port. VNC password saved to $vnc_password_file"
}

sudo apt update
sudo apt install -y auditd

Expand Down Expand Up @@ -129,6 +213,9 @@ echo "trying jupyter lab..."
nohup /opt/anaconda3/bin/jupyter lab --NotebookApp.token=$TOKEN --config=/home/$USER_ID/.jupyter/jupyter_notebook_config.py >/dev/null 2>&1 &
echo "jupyter lab listening!"

# noVNC 기동. 외부에서는 컨테이너의 6080 포트를 매핑해서 접속합니다.
start_novnc || echo "VNC/noVNC startup failed."

# ldconfig permission 오류 방지
# bash.bashrc에서 ldconfig 명령어 삭제 후 명령어 실행 및 결과 출력
sed -i '/ldconfig/d' /etc/bash.bashrc
Expand Down