|
1 | 1 | # ============================================================================== |
2 | | -# Dockerfile for a LIGHTWEIGHT, professional, and optimized code-server environment |
| 2 | +# Dockerfile for a professionally architected, optimized code-server environment |
| 3 | +# |
| 4 | +# Architecture: |
| 5 | +# - Installation by 'root': The entire Python/Conda toolchain is installed |
| 6 | +# by the root user into a system-wide location (/opt/conda). |
| 7 | +# - Usage by 'coder': The non-root 'coder' user is configured to seamlessly |
| 8 | +# use this immutable, pre-built environment. |
3 | 9 | # |
4 | 10 | # Features: |
5 | 11 | # - Base: code-server (latest) |
6 | 12 | # - Python: Miniforge (Conda) with a pre-created Python 3.11 environment |
7 | | -# - Package Manager: 'uv' (ultra-fast) and 'conda' |
| 13 | +# - Package Manager: 'uv' (installed via Conda for consistency) |
| 14 | +# - Root & Coder Access: 'python', 'conda', 'uv' are available for all users. |
8 | 15 | # - Optimization (China): |
9 | 16 | # - Timezone: Asia/Shanghai |
10 | | -# - PyPI Mirror: Alibaba Cloud (configured via uv.toml - CORRECT FORMAT) |
| 17 | +# - PyPI Mirror: Alibaba Cloud (configured for the 'coder' user) |
11 | 18 | # - Pre-installed Libraries: A minimal set (numpy, pandas, matplotlib) |
12 | | -# - Convenience: Auto-activates conda environment in the terminal |
| 19 | +# - Convenience: Auto-activates conda environment for the 'coder' user. |
13 | 20 | # ============================================================================== |
14 | 21 |
|
15 | | -# Step 1: Start from the official code-server base image. |
16 | | -FROM codercom/code-server:latest |
| 22 | +# --- Build Stage --- |
| 23 | +FROM codercom/code-server:latest as builder |
17 | 24 |
|
18 | | -# Step 2: Set arguments for tool versions for easy updates. |
| 25 | +# Set arguments for tool versions. |
19 | 26 | ARG MINIFORGE_VERSION=23.11.0-0 |
20 | 27 | ARG PYTHON_VERSION=3.11 |
21 | 28 |
|
22 | | -# Step 3: Define environment variables for paths and timezone. |
| 29 | +# Define global environment variables for paths and timezone. |
| 30 | +# This makes the toolchain available to ALL subsequent users (root and coder). |
23 | 31 | ENV CONDA_DIR=/opt/conda |
24 | | -ENV UV_DIR=/home/coder/.local |
25 | | -ENV PATH=${CONDA_DIR}/bin:${UV_DIR}/bin:${PATH} |
| 32 | +ENV PATH=${CONDA_DIR}/bin:${PATH} |
26 | 33 | ENV TZ=Asia/Shanghai |
27 | 34 |
|
28 | | -# Step 4: Switch to the ROOT user for system-level installations. |
| 35 | +# --- Installation Phase (as root) --- |
29 | 36 | USER root |
30 | 37 |
|
31 | | -# Step 5: Install system dependencies, set timezone, and install Miniforge. |
32 | 38 | RUN \ |
33 | | - # Update package lists and install necessary tools. |
| 39 | + # 1. Install system dependencies. |
34 | 40 | apt-get update && apt-get install -y --no-install-recommends \ |
35 | 41 | wget \ |
36 | 42 | curl \ |
37 | 43 | git \ |
38 | 44 | build-essential \ |
39 | 45 | tzdata \ |
40 | | - # Set the timezone non-interactively. |
41 | 46 | && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \ |
42 | | - # Download and install Miniforge. |
| 47 | + \ |
| 48 | + # 2. Install Miniforge (Conda). |
43 | 49 | && wget "https://github.com/conda-forge/miniforge/releases/download/${MINIFORGE_VERSION}/Miniforge3-${MINIFORGE_VERSION}-Linux-x86_64.sh" -O miniforge.sh \ |
44 | 50 | && /bin/bash miniforge.sh -b -p ${CONDA_DIR} \ |
45 | 51 | && rm miniforge.sh \ |
46 | | - # Give the 'coder' user ownership of the conda directory. |
47 | | - && chown -R coder:coder ${CONDA_DIR} \ |
48 | | - # Create symbolic links for 'conda' and 'python3' for easier root access (debugging). |
49 | | - && ln -s ${CONDA_DIR}/bin/conda /usr/local/bin/conda \ |
50 | | - && ln -s ${CONDA_DIR}/bin/python /usr/local/bin/python3 \ |
51 | | - # Clean up apt cache to reduce image size. |
| 52 | + \ |
| 53 | + # 3. Initialize Conda for the root's shell (useful for subsequent RUN commands). |
| 54 | + && conda init bash && . /root/.bashrc \ |
| 55 | + \ |
| 56 | + # 4. Install 'uv' into the base conda environment for system-wide access. |
| 57 | + && conda install -n base uv -c conda-forge -y \ |
| 58 | + \ |
| 59 | + # 5. Create the target Python environment. |
| 60 | + && conda create -n py${PYTHON_VERSION} python=${PYTHON_VERSION} -y \ |
| 61 | + \ |
| 62 | + # 6. Install core libraries into the new environment using 'uv'. |
| 63 | + && uv pip install --python=${CONDA_DIR}/envs/py${PYTHON_VERSION}/bin/python \ |
| 64 | + numpy \ |
| 65 | + pandas \ |
| 66 | + matplotlib \ |
| 67 | + \ |
| 68 | + # 7. Ensure the 'coder' user home directory exists and has correct ownership. |
| 69 | + && mkdir -p /home/coder && chown -R coder:coder /home/coder \ |
| 70 | + \ |
| 71 | + # 8. Clean up to reduce image size. |
52 | 72 | && apt-get clean \ |
53 | 73 | && rm -rf /var/lib/apt/lists/* |
54 | 74 |
|
55 | | -# Step 6: Switch back to the standard, non-root 'coder' user. |
| 75 | + |
| 76 | +# --- User Configuration Phase (as coder) --- |
56 | 77 | USER coder |
57 | 78 |
|
58 | | -# Step 7: As the 'coder' user, install 'uv', configure it, and create the environment. |
59 | 79 | RUN \ |
60 | | - # Install 'uv' (the fast Python package manager). |
61 | | - curl -LsSf https://astral.sh/uv/install.sh | sh && \ |
62 | | - \ |
63 | | - # Create the configuration directory for uv. |
| 80 | + # 1. Create the user-specific mirror configuration for 'uv'. |
64 | 81 | mkdir -p ~/.config/uv && \ |
65 | | - \ |
66 | | - ### --- [ THE REAL, FINAL FIX IS HERE ] --- ### |
67 | | - # Create the uv.toml with the CORRECT format for a global user config. |
68 | | - # It does NOT use the [tool.uv] section header. |
69 | 82 | printf 'index-url = "https://mirrors.aliyun.com/pypi/simple"\n' > ~/.config/uv/uv.toml && \ |
70 | 83 | \ |
71 | | - # Create the default conda environment. |
72 | | - conda create -n py${PYTHON_VERSION} python=${PYTHON_VERSION} -y && \ |
73 | | - \ |
74 | | - # Pre-install a minimal set of core data science libraries. |
75 | | - # This command will now succeed as uv can correctly parse its config. |
76 | | - uv pip install --python=${CONDA_DIR}/envs/py${PYTHON_VERSION}/bin/python \ |
77 | | - numpy \ |
78 | | - pandas \ |
79 | | - matplotlib && \ |
80 | | - \ |
81 | | - # Configure the shell to automatically activate this environment on login. |
| 84 | + # 2. Configure the user's shell to auto-activate the system-wide environment. |
| 85 | + conda init bash && \ |
82 | 86 | echo "conda activate py${PYTHON_VERSION}" >> ~/.bashrc |
83 | 87 |
|
84 | | -# Step 8: The base image's entrypoint will start code-server. |
| 88 | + |
| 89 | +# --- Verification and Final Stage --- |
| 90 | +# This stage ensures both root and coder environments are correctly configured. |
| 91 | +FROM builder |
| 92 | + |
| 93 | +# Final check as ROOT. |
| 94 | +RUN echo "Verifying root environment..." && \ |
| 95 | + python --version && \ |
| 96 | + conda --version && \ |
| 97 | + uv --version && \ |
| 98 | + echo "Root environment check PASSED!" |
| 99 | + |
| 100 | +# Final check as CODER. |
| 101 | +USER coder |
| 102 | +RUN echo "Verifying coder environment..." && \ |
| 103 | + # We must source .bashrc to load the 'conda activate' alias in a non-interactive shell. |
| 104 | + source ~/.bashrc && \ |
| 105 | + python --version && \ |
| 106 | + uv --version && \ |
| 107 | + echo "Coder environment check PASSED!" |
| 108 | + |
| 109 | +# The base image's CMD is inherited automatically. |
| 110 | +# No need to specify it again. |
0 commit comments