Skip to content

Commit ccb3731

Browse files
author
ide-coder
committed
feat: add volume mount compatibility for /home/coder
- Move Go tools from /home/coder/go/bin to /opt/go-tools/bin - Add config templates in /opt/dev-configs/ - Add init-home.sh script to auto-initialize configs on container start - Add custom entrypoint to handle volume mount initialization - Update README with mounting entire /home/coder directory section
1 parent d1aec2c commit ccb3731

3 files changed

Lines changed: 168 additions & 39 deletions

File tree

Dockerfile

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,22 @@ RUN apt-get update && apt-get install -y --no-install-recommends sudo \
3939
# Layer 3: Go (latest) with China mirror and tools
4040
ENV GO_VERSION=1.24.0
4141
ENV GOPROXY=https://goproxy.cn,direct
42+
# GOPATH for user packages (can be mounted), tools installed to /opt/go-tools
4243
ENV GOPATH=/home/coder/go
43-
ENV PATH=/usr/local/go/bin:/home/coder/go/bin:$PATH
44+
ENV GO_TOOLS_PATH=/opt/go-tools
45+
ENV PATH=/usr/local/go/bin:/opt/go-tools/bin:/home/coder/go/bin:$PATH
4446

4547
RUN ARCH=$(dpkg --print-architecture) \
4648
&& curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf - \
4749
&& go version
4850

49-
# Install Go tools
50-
RUN go install golang.org/x/tools/gopls@latest \
51-
&& go install github.com/go-delve/delve/cmd/dlv@latest \
52-
&& go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest \
53-
&& go install golang.org/x/tools/cmd/goimports@latest
51+
# Install Go tools to /opt/go-tools (not affected by volume mounts on /home/coder)
52+
RUN mkdir -p /opt/go-tools \
53+
&& GOPATH=/opt/go-tools go install golang.org/x/tools/gopls@latest \
54+
&& GOPATH=/opt/go-tools go install github.com/go-delve/delve/cmd/dlv@latest \
55+
&& GOPATH=/opt/go-tools go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest \
56+
&& GOPATH=/opt/go-tools go install golang.org/x/tools/cmd/goimports@latest \
57+
&& chown -R coder:coder /opt/go-tools
5458

5559
# Create symlinks for go commands (ensures availability even when PATH is reset)
5660
RUN ln -s /usr/local/go/bin/go /usr/local/bin/go \
@@ -157,25 +161,25 @@ RUN echo "---\n:sources:\n - https://gems.ruby-china.com/" > /home/coder/.gemrc
157161
RUN echo '#!/bin/sh\n\
158162
# Development tools PATH configuration\n\
159163
# Note: Symlinks in /usr/local/bin provide fallback, this is additional coverage\n\
160-
export PATH=/opt/rbenv/bin:/opt/rbenv/shims:/usr/local/go/bin:/home/coder/go/bin:/opt/temurin-21-jdk/bin:/opt/conda/bin:$PATH' > /etc/profile.d/dev-tools.sh \
164+
export PATH=/opt/go-tools/bin:/opt/rbenv/bin:/opt/rbenv/shims:/usr/local/go/bin:/home/coder/go/bin:/opt/temurin-21-jdk/bin:/opt/conda/bin:$PATH' > /etc/profile.d/dev-tools.sh \
161165
&& chmod +x /etc/profile.d/dev-tools.sh
162166

163-
# Create directories for external mounting support
164-
RUN mkdir -p /home/coder/project \
165-
&& mkdir -p /home/coder/.local/share/code-server \
166-
&& mkdir -p /home/coder/.local/share/pnpm \
167-
&& mkdir -p /home/coder/.m2/repository \
168-
&& mkdir -p /home/coder/.config/pip \
169-
&& mkdir -p /home/coder/.npm \
170-
&& mkdir -p /home/coder/.cache/uv \
171-
&& mkdir -p /home/coder/.cache/pip \
172-
&& mkdir -p /home/coder/go
167+
# Create config templates directory (for volume mount compatibility)
168+
# When /home/coder is mounted externally, these templates will be used to initialize configs
169+
RUN mkdir -p /opt/dev-configs
173170

174-
# Declare volumes for external mounting (optional, users can override with -v)
175-
# These can be mounted to persist data across container restarts
176-
VOLUME ["/home/coder/project"]
171+
# bashrc append content template
172+
RUN echo '\n\
173+
# Restore Docker ENV PATH (VS Code terminal resets PATH)\n\
174+
export PATH=/opt/go-tools/bin:/opt/rbenv/bin:/opt/rbenv/shims:/opt/temurin-21-jdk/bin:/opt/conda/bin:/usr/local/go/bin:/home/coder/go/bin:$PATH\n\
175+
\n\
176+
# Initialize rbenv\n\
177+
eval "$(/opt/rbenv/bin/rbenv init - bash)"' > /opt/dev-configs/bashrc-append.sh
178+
179+
# gemrc template
180+
RUN echo '---\n:sources:\n - https://gems.ruby-china.com/' > /opt/dev-configs/gemrc
177181

178-
# Maven settings.xml with Aliyun mirror
182+
# Maven settings.xml template
179183
RUN echo '<?xml version="1.0" encoding="UTF-8"?>\n\
180184
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"\n\
181185
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n\
@@ -188,31 +192,56 @@ RUN echo '<?xml version="1.0" encoding="UTF-8"?>\n\
188192
<url>https://maven.aliyun.com/repository/public</url>\n\
189193
</mirror>\n\
190194
</mirrors>\n\
191-
</settings>' > /home/coder/.m2/settings.xml
195+
</settings>' > /opt/dev-configs/m2-settings.xml
192196

193-
# pip config with Tsinghua mirror
194-
RUN echo '[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple' > /home/coder/.config/pip/pip.conf
197+
# pip config template
198+
RUN echo '[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple' > /opt/dev-configs/pip.conf
195199

196-
# conda config - Miniforge uses conda-forge by default (no Anaconda ToS)
197-
RUN /opt/conda/bin/conda config --set show_channel_urls yes
200+
# Copy initialization script
201+
COPY scripts/init-home.sh /opt/dev-configs/init-home.sh
202+
RUN chmod +x /opt/dev-configs/init-home.sh
203+
204+
# Create directories for external mounting support
205+
RUN mkdir -p /home/coder/project \
206+
&& mkdir -p /home/coder/.local/share/code-server \
207+
&& mkdir -p /home/coder/.local/share/pnpm \
208+
&& mkdir -p /home/coder/.m2/repository \
209+
&& mkdir -p /home/coder/.config/pip \
210+
&& mkdir -p /home/coder/.npm \
211+
&& mkdir -p /home/coder/.cache/uv \
212+
&& mkdir -p /home/coder/.cache/pip \
213+
&& mkdir -p /home/coder/go
198214

199-
# npm config (already configured in Layer 5)
200-
RUN mkdir -p /home/coder/.npm
215+
# Declare volumes for external mounting (optional, users can override with -v)
216+
# These can be mounted to persist data across container restarts
217+
VOLUME ["/home/coder/project"]
201218

202-
# Add PATH restoration and rbenv initialization to .bashrc
203-
# VS Code terminal is non-login shell, only .bashrc is read
204-
# Use >> to append instead of > to avoid overwriting existing .bashrc
205-
RUN echo '\n\
206-
# Restore Docker ENV PATH (VS Code terminal resets PATH)\n\
207-
export PATH=/opt/rbenv/bin:/opt/rbenv/shims:/opt/temurin-21-jdk/bin:/opt/conda/bin:/usr/local/go/bin:/home/coder/go/bin:$PATH\n\
208-
\n\
209-
# Initialize rbenv\n\
210-
eval "$(/opt/rbenv/bin/rbenv init - bash)"' >> /home/coder/.bashrc
219+
# Initialize config files from templates
220+
RUN cp /opt/dev-configs/gemrc /home/coder/.gemrc \
221+
&& cp /opt/dev-configs/m2-settings.xml /home/coder/.m2/settings.xml \
222+
&& cp /opt/dev-configs/pip.conf /home/coder/.config/pip/pip.conf \
223+
&& cat /opt/dev-configs/bashrc-append.sh >> /home/coder/.bashrc
224+
225+
# conda config - Miniforge uses conda-forge by default (no Anaconda ToS)
226+
RUN /opt/conda/bin/conda config --set show_channel_urls yes
211227

212228
# Set ownership for coder user
213-
# Note: /opt/rbenv is owned by root, but accessible by all users
214229
RUN chown -R coder:coder /home/coder \
215-
&& chown -R coder:coder /opt/conda
230+
&& chown -R coder:coder /opt/conda \
231+
&& chown -R coder:coder /opt/go-tools
232+
233+
# Create entrypoint script that initializes home directory on container start
234+
# This ensures configs are properly set when /home/coder is mounted externally
235+
RUN echo '#!/bin/bash\n\
236+
# Initialize home directory if mounted externally\n\
237+
/opt/dev-configs/init-home.sh\n\
238+
# Execute the original entrypoint or command\n\
239+
exec "$@"' > /entrypoint.sh \
240+
&& chmod +x /entrypoint.sh
216241

217242
USER coder
218243
WORKDIR /home/coder/project
244+
245+
# Use custom entrypoint to handle volume mount initialization
246+
ENTRYPOINT ["/entrypoint.sh"]
247+
CMD ["code-server", "--bind-addr", "0.0.0.0:8080", "."]

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,44 @@ services:
132132
- Go tools installed via `go install`
133133
- Maven dependencies cached locally
134134

135+
## Mounting Entire /home/coder Directory
136+
137+
You can mount the entire `/home/coder` directory for maximum persistence:
138+
139+
```bash
140+
docker run -d \
141+
--name ide-code-server \
142+
-p 8080:8080 \
143+
-v $(pwd)/coder-home:/home/coder \
144+
-e PASSWORD=yourpassword \
145+
ghcr.io/your-username/ide-code-server:latest
146+
```
147+
148+
### Auto-Initialization
149+
150+
When `/home/coder` is mounted (especially as an empty directory), the container automatically initializes:
151+
152+
| File | Purpose |
153+
|------|---------|
154+
| `.bashrc` | PATH restoration and rbenv initialization |
155+
| `.gemrc` | Ruby China mirror configuration |
156+
| `.m2/settings.xml` | Maven Aliyun mirror configuration |
157+
| `.config/pip/pip.conf` | pip Tsinghua mirror configuration |
158+
159+
Required directories are also created automatically.
160+
161+
### System Tools (Not Affected by Mounts)
162+
163+
The following components are installed in system directories and remain available regardless of volume mounts:
164+
165+
| Component | Location | Tools |
166+
|-----------|----------|-------|
167+
| Go Tools | `/opt/go-tools/bin` | gopls, dlv, golangci-lint, goimports |
168+
| Ruby (rbenv) | `/opt/rbenv` | ruby, gem, rails, bundler |
169+
| Python/conda | `/opt/conda` | python, pip, conda |
170+
| JDK | `/opt/temurin-21-jdk` | java, javac, jar |
171+
| Maven | `/opt/apache-maven` | mvn |
172+
135173
## Installed Languages
136174

137175
| Language | Version | Tools | Mirror |

scripts/init-home.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/bin/bash
2+
# init-home.sh - Initialize /home/coder directory for volume mount compatibility
3+
# This script ensures configuration files and directories exist when /home/coder is mounted externally
4+
5+
set -e
6+
7+
HOME_DIR="/home/coder"
8+
CONFIG_TEMPLATES="/opt/dev-configs"
9+
10+
# Create necessary directories
11+
echo "Creating directories..."
12+
mkdir -p "$HOME_DIR/project"
13+
mkdir -p "$HOME_DIR/.local/share/code-server"
14+
mkdir -p "$HOME_DIR/.local/share/pnpm"
15+
mkdir -p "$HOME_DIR/.m2/repository"
16+
mkdir -p "$HOME_DIR/.config/pip"
17+
mkdir -p "$HOME_DIR/.npm"
18+
mkdir -p "$HOME_DIR/.cache/uv"
19+
mkdir -p "$HOME_DIR/.cache/pip"
20+
mkdir -p "$HOME_DIR/go"
21+
22+
# Initialize .bashrc if needed
23+
BASHRC_FILE="$HOME_DIR/.bashrc"
24+
if [ -f "$BASHRC_FILE" ]; then
25+
# Check if PATH restoration already exists
26+
if ! grep -q "# Restore Docker ENV PATH" "$BASHRC_FILE"; then
27+
echo "Appending PATH configuration to .bashrc..."
28+
cat "$CONFIG_TEMPLATES/bashrc-append.sh" >> "$BASHRC_FILE"
29+
fi
30+
else
31+
echo "Creating .bashrc..."
32+
cp "$CONFIG_TEMPLATES/bashrc-append.sh" "$BASHRC_FILE"
33+
fi
34+
35+
# Initialize .gemrc if not exists
36+
GEMRC_FILE="$HOME_DIR/.gemrc"
37+
if [ ! -f "$GEMRC_FILE" ]; then
38+
echo "Creating .gemrc..."
39+
cp "$CONFIG_TEMPLATES/gemrc" "$GEMRC_FILE"
40+
fi
41+
42+
# Initialize Maven settings.xml if not exists
43+
M2_SETTINGS="$HOME_DIR/.m2/settings.xml"
44+
if [ ! -f "$M2_SETTINGS" ]; then
45+
echo "Creating Maven settings.xml..."
46+
cp "$CONFIG_TEMPLATES/m2-settings.xml" "$M2_SETTINGS"
47+
fi
48+
49+
# Initialize pip config if not exists
50+
PIP_CONF="$HOME_DIR/.config/pip/pip.conf"
51+
if [ ! -f "$PIP_CONF" ]; then
52+
echo "Creating pip.conf..."
53+
cp "$CONFIG_TEMPLATES/pip.conf" "$PIP_CONF"
54+
fi
55+
56+
# Set ownership for coder user (if running as root)
57+
if [ "$(id -u)" = "0" ]; then
58+
echo "Setting ownership..."
59+
chown -R coder:coder "$HOME_DIR"
60+
fi
61+
62+
echo "Initialization complete."

0 commit comments

Comments
 (0)