Skip to content

Commit 677a5bb

Browse files
committed
✨ Replace the terminal service base image and support mounting local file paths
1 parent a514425 commit 677a5bb

File tree

11 files changed

+208
-43
lines changed

11 files changed

+208
-43
lines changed

doc/docs/en/deployment/docker-build.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.c
1919
# 📚 build documentation for multiple architectures
2020
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t nexent/nexent-docs -f make/docs/Dockerfile . --push
2121
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.ccs.tencentyun.com/nexent-hub/nexent-docs -f make/docs/Dockerfile . --push
22+
23+
# 💻 build Ubuntu Terminal for multiple architectures
24+
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t nexent/nexent-terminal -f make/terminal/Dockerfile . --push
25+
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.ccs.tencentyun.com/nexent-hub/nexent-terminal -f make/terminal/Dockerfile . --push
2226
```
2327

2428
### 💻 Local Development Build
@@ -35,6 +39,9 @@ docker build --progress=plain -t nexent/nexent-web -f make/web/Dockerfile .
3539

3640
# 📚 Build documentation image (current architecture only)
3741
docker build --progress=plain -t nexent/nexent-docs -f make/docs/Dockerfile .
42+
43+
# 💻 Build OpenSSH Server image (current architecture only)
44+
docker build --progress=plain -t nexent/nexent-ubuntu-terminal -f make/terminal/Dockerfile .
3845
```
3946

4047
### 🧹 Clean up Docker resources
@@ -66,6 +73,23 @@ docker builder prune -f && docker system prune -f
6673
- Built from `make/docs/Dockerfile`
6774
- Provides project documentation and API reference
6875

76+
#### OpenSSH Server Image (nexent/nexent-ubuntu-terminal)
77+
- Ubuntu 24.04-based SSH server container
78+
- Built from `make/terminal/Dockerfile`
79+
- Pre-installed with Conda, Python, Git and other development tools
80+
- Supports SSH key authentication with username `linuxserver.io`
81+
- Provides complete development environment
82+
83+
##### Pre-installed Tools and Features
84+
- **Python Environment**: Python 3 + pip + virtualenv
85+
- **Conda Management**: Miniconda3 environment management
86+
- **Development Tools**: Git, Vim, Nano, Curl, Wget
87+
- **Build Tools**: build-essential, Make
88+
- **SSH Service**: Port 2222, root login and password authentication disabled
89+
- **User Permissions**: `linuxserver.io` user has sudo privileges (no password required)
90+
- **Timezone Setting**: Asia/Shanghai
91+
- **Security Configuration**: SSH key authentication, 60-minute session timeout
92+
6993
### 🏷️ Tagging Strategy
7094

7195
Each image is pushed to two repositories:
@@ -77,6 +101,7 @@ All images include:
77101
- `nexent/nexent-data-process` - Data processing service
78102
- `nexent/nexent-web` - Next.js frontend application
79103
- `nexent/nexent-docs` - Vitepress documentation site
104+
- `nexent/nexent-ubuntu-terminal` - OpenSSH development server container
80105

81106
## 📚 Documentation Image Standalone Deployment
82107

doc/docs/zh/deployment/docker-build.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.c
2323
# 📚 为多个架构构建文档
2424
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t nexent/nexent-docs -f make/docs/Dockerfile . --push
2525
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.ccs.tencentyun.com/nexent-hub/nexent-docs -f make/docs/Dockerfile . --push
26+
27+
# 💻 为多个架构构建 Ubuntu Terminal
28+
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t nexent/nexent-terminal -f make/terminal/Dockerfile . --push
29+
docker buildx build --progress=plain --platform linux/amd64,linux/arm64 -t ccr.ccs.tencentyun.com/nexent-hub/nexent-terminal -f make/terminal/Dockerfile . --push
2630
```
2731

2832
## 💻 本地开发构建
@@ -39,6 +43,9 @@ docker build --progress=plain -t nexent/nexent-web -f make/web/Dockerfile .
3943

4044
# 📚 构建文档镜像(仅当前架构)
4145
docker build --progress=plain -t nexent/nexent-docs -f make/docs/Dockerfile .
46+
47+
# 💻 构建 OpenSSH Server 镜像(仅当前架构)
48+
docker build --progress=plain -t nexent/nexent-ubuntu-terminal -f make/terminal/Dockerfile .
4249
```
4350

4451
## 🔧 镜像说明
@@ -63,6 +70,23 @@ docker build --progress=plain -t nexent/nexent-docs -f make/docs/Dockerfile .
6370
- 基于 `make/docs/Dockerfile` 构建
6471
- 提供项目文档和 API 参考
6572

73+
### OpenSSH Server 镜像 (nexent/nexent-ubuntu-terminal)
74+
- 基于 Ubuntu 24.04 的 SSH 服务器容器
75+
- 基于 `make/terminal/Dockerfile` 构建
76+
- 预装 Conda、Python、Git 等开发工具
77+
- 支持 SSH 密钥认证,用户名为 `linuxserver.io`
78+
- 提供完整的开发环境
79+
80+
#### 预装工具和特性
81+
- **Python 环境**: Python 3 + pip + virtualenv
82+
- **Conda 管理**: Miniconda3 环境管理
83+
- **开发工具**: Git、Vim、Nano、Curl、Wget
84+
- **构建工具**: build-essential、Make
85+
- **SSH 服务**: 端口 2222,禁用 root 登录和密码认证
86+
- **用户权限**: `linuxserver.io` 用户具有 sudo 权限(无需密码)
87+
- **时区设置**: Asia/Shanghai
88+
- **安全配置**: SSH 密钥认证,会话超时 60 分钟
89+
6690
## 🏷️ 标签策略
6791

6892
每个镜像都会推送到两个仓库:
@@ -74,6 +98,7 @@ docker build --progress=plain -t nexent/nexent-docs -f make/docs/Dockerfile .
7498
- `nexent/nexent-data-process` - 数据处理服务
7599
- `nexent/nexent-web` - Next.js 前端应用
76100
- `nexent/nexent-docs` - Vitepress 文档站点
101+
- `nexent/nexent-ubuntu-terminal` - OpenSSH 开发服务器容器
77102

78103
## 📚 文档镜像独立部署
79104

@@ -113,6 +138,6 @@ docker stop nexent-docs
113138
docker rm nexent-docs
114139
```
115140

116-
## 🚀 部署建议
141+
## 部署建议
117142

118143
构建完成后,可以使用 `docker/deploy.sh` 脚本进行部署,或者直接使用 `docker-compose` 启动服务。

docker/.env.beta

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ ELASTICSEARCH_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:8.17.4
66
POSTGRESQL_IMAGE=postgres:15-alpine
77
REDIS_IMAGE=redis:alpine
88
MINIO_IMAGE=quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z
9-
OPENSSH_SERVER_IMAGE=lscr.io/linuxserver/openssh-server:latest
9+
OPENSSH_SERVER_IMAGE=nexent-ubuntu-terminal:latest

docker/.env.general

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ ELASTICSEARCH_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:8.17.4
66
POSTGRESQL_IMAGE=postgres:15-alpine
77
REDIS_IMAGE=redis:alpine
88
MINIO_IMAGE=quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z
9-
OPENSSH_SERVER_IMAGE=lscr.io/linuxserver/openssh-server:latest
9+
OPENSSH_SERVER_IMAGE=nexent-ubuntu-terminal:latest

docker/.env.mainland

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ ELASTICSEARCH_IMAGE=elastic.m.daocloud.io/elasticsearch/elasticsearch:8.17.4
66
POSTGRESQL_IMAGE=docker.m.daocloud.io/postgres:15-alpine
77
REDIS_IMAGE=docker.m.daocloud.io/redis:alpine
88
MINIO_IMAGE=quay.m.daocloud.io/minio/minio:RELEASE.2023-12-20T01-00-02Z
9-
OPENSSH_SERVER_IMAGE=docker.m.daocloud.io/linuxserver/openssh-server:latest
9+
OPENSSH_SERVER_IMAGE=nexent-ubuntu-terminal:latest

docker/deploy.sh

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,6 @@ generate_ssh_keys() {
156156
cp "openssh-server/ssh-keys/openssh_server_key.pub" "openssh-server/config/authorized_keys"
157157
chmod 644 "openssh-server/config/authorized_keys"
158158

159-
# Setup package installation script
160-
setup_package_install_script
161-
162159
# Set SSH key path in environment
163160
SSH_PRIVATE_KEY_PATH="$(pwd)/openssh-server/ssh-keys/openssh_server_key"
164161
export SSH_PRIVATE_KEY_PATH
@@ -185,7 +182,7 @@ generate_ssh_keys() {
185182
TEMP_OUTPUT="/tmp/ssh_keygen_output_$$.txt"
186183

187184
# Generate ed25519 key pair using the openssh-server container
188-
if docker run --rm -i --entrypoint //keygen.sh "$OPENSSH_SERVER_IMAGE" <<< "1" > "$TEMP_OUTPUT" 2>&1; then
185+
if docker run --rm -i "$OPENSSH_SERVER_IMAGE" bash -c "ssh-keygen -t ed25519 -f /tmp/id_ed25519 -N '' && cat /tmp/id_ed25519 && echo '---' && cat /tmp/id_ed25519.pub" > "$TEMP_OUTPUT" 2>&1; then
189186
echo " 🔍 SSH key generation completed, extracting keys..."
190187

191188
# Extract private key (everything between -----BEGIN and -----END)
@@ -226,9 +223,6 @@ generate_ssh_keys() {
226223
cp "openssh-server/ssh-keys/openssh_server_key.pub" "openssh-server/config/authorized_keys"
227224
chmod 644 "openssh-server/config/authorized_keys"
228225

229-
# Setup package installation script
230-
setup_package_install_script
231-
232226
# Set SSH key path in environment
233227
SSH_PRIVATE_KEY_PATH="$(pwd)/openssh-server/ssh-keys/openssh_server_key"
234228
export SSH_PRIVATE_KEY_PATH
@@ -643,16 +637,16 @@ select_deployment_version() {
643637
echo ""
644638
}
645639

646-
pull_openssh_images() {
647-
# Function to pull openssh images
640+
build_ubuntu_terminal_image() {
641+
# Function to build openssh-server image
648642

649-
echo "🐳 Pulling openssh-server image for Terminal tool..."
650-
if ! docker pull "$OPENSSH_SERVER_IMAGE"; then
651-
echo " ❌ ERROR Failed to pull openssh-server image: $OPENSSH_SERVER_IMAGE"
643+
echo "🐳 Building openssh-server image for Terminal tool..."
644+
if ! docker build -t "$OPENSSH_SERVER_IMAGE" -f ../make/terminal/Dockerfile ..; then
645+
echo " ❌ ERROR Failed to build openssh-server image"
652646
ERROR_OCCURRED=1
653647
return 1
654648
fi
655-
echo " ✅ Successfully pulled openssh-server image"
649+
echo " ✅ Successfully built openssh-server image"
656650
echo ""
657651
echo "--------------------------------"
658652
echo ""
@@ -714,6 +708,31 @@ select_terminal_tool() {
714708
export COMPOSE_PROFILES="${COMPOSE_PROFILES:+$COMPOSE_PROFILES,}terminal"
715709
echo "✅ Terminal tool enabled 🔧"
716710
echo " 🔧 Deploying an openssh-server container for secure command execution"
711+
712+
# Ask user to specify directory mapping
713+
default_terminal_dir="/opt/terminal"
714+
echo " 📁 Terminal directory configuration:"
715+
echo " • Container path: /opt/terminal (fixed)"
716+
echo " • Host path: You can specify any directory on your host machine"
717+
echo " • Default host path: /opt/terminal (recommended)"
718+
echo ""
719+
read -p " 📁 Enter host directory to mount (default: /opt/terminal): " terminal_mount_dir
720+
terminal_mount_dir=$(sanitize_input "$terminal_mount_dir")
721+
TERMINAL_MOUNT_DIR="${terminal_mount_dir:-$default_terminal_dir}"
722+
723+
# Save to environment variables
724+
export TERMINAL_MOUNT_DIR
725+
726+
# Add to .env file
727+
if grep -q "^TERMINAL_MOUNT_DIR=" .env; then
728+
sed -i.bak "s~^TERMINAL_MOUNT_DIR=.*~TERMINAL_MOUNT_DIR=$TERMINAL_MOUNT_DIR~" .env
729+
else
730+
echo "TERMINAL_MOUNT_DIR=$TERMINAL_MOUNT_DIR" >> .env
731+
fi
732+
733+
echo " 📁 Terminal mount configuration:"
734+
echo " • Host: $TERMINAL_MOUNT_DIR"
735+
echo " • Container: /opt/terminal"
717736
else
718737
export ENABLE_TERMINAL_TOOL="false"
719738
echo "🚫 Terminal tool disabled"
@@ -797,7 +816,7 @@ main_deploy() {
797816
generate_minio_ak_sk || { echo "❌ MinIO key generation failed"; exit 1; }
798817

799818
if [ "$ENABLE_TERMINAL_TOOL" = "true" ]; then
800-
pull_openssh_images || { echo "Openssh image pull failed"; exit 1; }
819+
build_ubuntu_terminal_image || { echo "Ubuntu terminal image build failed"; exit 1; }
801820
generate_ssh_keys || { echo "❌ SSH key generation failed"; exit 1; }
802821
fi
803822

docker/docker-compose.prod.yml

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,11 @@ services:
202202
container_name: nexent-openssh-server
203203
hostname: nexent-openssh-server
204204
environment:
205-
PUID: 1000
206-
PGID: 1000
207-
TZ: "Asia/Shanghai"
208-
PUBLIC_KEY_FILE: /config/authorized_keys
209-
SUDO_ACCESS: "true"
210-
PASSWORD_ACCESS: "false"
211-
LOG_STDOUT: "true"
212-
DOCKER_MODS: linuxserver/mods:universal-package-install
213-
INSTALL_PACKAGES: git|make|curl|vim|wget
205+
- TZ=Asia/Shanghai
206+
- DEV_USER=linuxserver.io
214207
volumes:
215-
- ${ROOT_DIR}/openssh-server/config:/config
216-
- ${ROOT_DIR}/openssh-server/config/custom-cont-init.d:/custom-cont-init.d:ro
208+
- ${TERMINAL_MOUNT_DIR:-./workspace}:/opt/terminal
209+
- ${ROOT_DIR}/openssh-server/config:/tmp/ssh_keys:ro # 只读挂载SSH公钥
217210
networks:
218211
- nexent
219212
restart: always

docker/docker-compose.yml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -217,20 +217,13 @@ services:
217217
container_name: nexent-openssh-server
218218
hostname: nexent-openssh-server
219219
environment:
220-
PUID: 1000
221-
PGID: 1000
222-
TZ: "Asia/Shanghai"
223-
PUBLIC_KEY_FILE: /config/authorized_keys
224-
SUDO_ACCESS: "true"
225-
PASSWORD_ACCESS: "false"
226-
LOG_STDOUT: "true"
227-
DOCKER_MODS: linuxserver/mods:universal-package-install
228-
INSTALL_PACKAGES: git|make|curl|vim|wget
220+
- TZ=Asia/Shanghai
221+
- DEV_USER=linuxserver.io
229222
ports:
230-
- "2222:2222" # SSH port
223+
- "2222:22" # SSH port
231224
volumes:
232-
- ${ROOT_DIR}/openssh-server/config:/config
233-
- ${ROOT_DIR}/openssh-server/config/custom-cont-init.d:/custom-cont-init.d:ro
225+
- ${TERMINAL_MOUNT_DIR:-./workspace}:/opt/terminal
226+
- ${ROOT_DIR}/openssh-server/ssh-keys:/tmp/ssh_keys:ro
234227
networks:
235228
- nexent
236229
restart: always

make/terminal/Dockerfile

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
FROM ubuntu:24.04
2+
3+
# Set environment variables
4+
ENV DEBIAN_FRONTEND=noninteractive
5+
ENV TZ=Asia/Shanghai
6+
ENV CONDA_DIR=/opt/conda
7+
ENV PATH=$CONDA_DIR/bin:$PATH
8+
9+
# Install base tools and dependencies
10+
RUN apt-get update && apt-get install -y \
11+
openssh-server \
12+
sudo \
13+
curl \
14+
wget \
15+
git \
16+
vim \
17+
nano \
18+
build-essential \
19+
python3 \
20+
python3-pip \
21+
python3-venv \
22+
ca-certificates \
23+
gnupg \
24+
lsb-release \
25+
software-properties-common \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
# Create development user
29+
ARG DEV_USER=linuxserver.io
30+
RUN useradd -m -s /bin/bash $DEV_USER && \
31+
usermod -aG sudo $DEV_USER && \
32+
echo "$DEV_USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
33+
34+
# Configure SSH - disable root login + disable password authentication
35+
RUN mkdir /var/run/sshd && \
36+
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
37+
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
38+
39+
# Install Miniconda
40+
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && \
41+
bash /tmp/miniconda.sh -b -p $CONDA_DIR && \
42+
rm /tmp/miniconda.sh
43+
44+
# Set conda permissions
45+
RUN chown -R $DEV_USER:$DEV_USER $CONDA_DIR
46+
47+
# Create .ssh directory
48+
RUN mkdir -p /home/$DEV_USER/.ssh && \
49+
chown $DEV_USER:$DEV_USER /home/$DEV_USER/.ssh && \
50+
chmod 700 /home/$DEV_USER/.ssh
51+
52+
# Create default working directory
53+
RUN mkdir -p /opt/terminal && \
54+
chown $DEV_USER:$DEV_USER /opt/terminal
55+
56+
# Set working directory
57+
WORKDIR /opt
58+
59+
# Entrypoint script
60+
COPY make/terminal/entrypoint.sh /entrypoint.sh
61+
RUN chmod +x /entrypoint.sh
62+
63+
EXPOSE 22
64+
ENTRYPOINT ["/entrypoint.sh"]

make/terminal/entrypoint.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Get user name
5+
DEV_USER=${DEV_USER:-linuxserver.io}
6+
USER_HOME="/home/$DEV_USER"
7+
8+
# Allow login (unlock)
9+
passwd -u "$DEV_USER" 2>/dev/null || true
10+
11+
# Ensure shell is available
12+
usermod -s /bin/bash "$DEV_USER" 2>/dev/null || true
13+
14+
# Ensure user .ssh directory exists
15+
mkdir -p "$USER_HOME/.ssh"
16+
chown $DEV_USER:$DEV_USER "$USER_HOME/.ssh"
17+
chmod 700 "$USER_HOME/.ssh"
18+
19+
# Configure public key authentication (Ed25519)
20+
if [ -f /tmp/ssh_keys/openssh_server_key.pub ]; then
21+
cp /tmp/ssh_keys/openssh_server_key.pub "$USER_HOME/.ssh/authorized_keys"
22+
chown $DEV_USER:$DEV_USER "$USER_HOME/.ssh/authorized_keys"
23+
chmod 600 "$USER_HOME/.ssh/authorized_keys"
24+
echo "✅ SSH public key successfully configured (Ed25519)"
25+
else
26+
echo "⚠️ Warning: SSH public key file not found /tmp/ssh_keys/openssh_server_key.pub"
27+
echo "⚠️ Unable to connect to container via SSH"
28+
fi
29+
30+
# Configure SSH timeout settings
31+
echo "Configuring SSH timeout settings (60 minutes)..."
32+
cat >> /etc/ssh/sshd_config << 'SSHD_EOF'
33+
34+
# Nexent Terminal Tool - Session timeout configuration (60 minutes = 3600 seconds)
35+
ClientAliveInterval 300
36+
ClientAliveCountMax 12
37+
SSHD_EOF
38+
39+
echo "SSH timeout configuration applied successfully"
40+
41+
# Start SSH service
42+
if [ $# -gt 0 ]; then
43+
exec "$@"
44+
else
45+
exec /usr/sbin/sshd -D -d
46+
fi

0 commit comments

Comments
 (0)