diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..94870f4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git +build.sh +README.md +.dockerignore diff --git a/Dockerfile b/Dockerfile index be21516..2b8bc2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,39 +2,38 @@ ARG UBUNTU_VER=24.04 FROM ubuntu:${UBUNTU_VER} -ENV DEBIAN_FRONTEND=noninteractive +ARG DEBIAN_FRONTEND=noninteractive # Enable autocompletion and install packages in optimized layers RUN rm /etc/apt/apt.conf.d/docker-* && \ echo 'if [ -f /etc/bash_completion ] && ! shopt -oq posix; then . /etc/bash_completion; fi' >> /root/.bashrc RUN apt update && apt install -y \ - # Basic utilities - curl wget nano lsb-release sudo bash-completion jq git screen cron \ - # Basic networking tools - net-tools iputils-ping iproute2 iptables dnsutils \ - # Network diagnostic and probing tools - tcpdump traceroute netcat-openbsd nmap telnet whois mtr-tiny socat \ - # Network performance tools - iperf3 speedtest-cli \ - # Network configuration utilities - bridge-utils vlan \ - # VPN and tunneling tools - wireguard-tools openvpn stunnel4 \ - # Packet analysis tools - tshark \ - # Programming languages and runtimes - python3 python3-pip python3-venv python3-dev python-is-python3 \ - # Development tools - software-properties-common build-essential \ - # Remote access - openssh-server \ - # Localization - locales - -# Install Node.js using official NodeSource repository -RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && \ - apt-get install -y nodejs + # Basic utilities + curl wget nano lsb-release sudo bash-completion jq git screen cron \ + # Basic networking tools + net-tools iputils-ping iproute2 iptables dnsutils \ + # Network diagnostic and probing tools + tcpdump traceroute netcat-openbsd nmap telnet whois mtr-tiny socat \ + # Network performance tools + iperf3 speedtest-cli \ + # Network configuration utilities + bridge-utils vlan \ + # VPN and tunneling tools + wireguard-tools openvpn stunnel4 \ + # Packet analysis tools + tshark \ + # Programming languages and runtimes + python3 python3-pip python3-venv python3-dev python-is-python3 \ + # Development tools + software-properties-common build-essential \ + # Remote access + openssh-server \ + # Localization + locales \ + # Install Node.js using official NodeSource repository + && curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \ + && apt-get install -y nodejs # Configure locales ENV LC_ALL=en_US.UTF-8 @@ -63,9 +62,6 @@ RUN chmod +x /entrypoint.sh ENV LOG_FILE=/dev/null -# Reset DEBIAN_FRONTEND -ENV DEBIAN_FRONTEND="" - EXPOSE 22 CMD ["/entrypoint.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7bce75 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# Ubuntu Dev Environment + +Multi-arch (`amd64`/`arm64`) Ubuntu Docker images with pre-installed networking, development, and debugging tools. Built for use as a general-purpose dev environment. + +## Available Images + +| Version | Gitea | GitHub | +|---------|-------|--------| +| 24.04 (latest) | `gitea.ahkhan.me/docker/ubuntu-24.04` | `ghcr.io/ahkhan03/ubuntu-24.04` | +| 22.04 | `gitea.ahkhan.me/docker/ubuntu-22.04` | `ghcr.io/ahkhan03/ubuntu-22.04` | +| 20.04 | `gitea.ahkhan.me/docker/ubuntu-20.04` | `ghcr.io/ahkhan03/ubuntu-20.04` | + +The `ubuntu:latest` tag points to Ubuntu 24.04. + +## Environment Variables + +### SSH + +| Variable | Default | Description | +|----------|---------|-------------| +| `ENABLE_SSH` | `true` | Start the SSH server on port 22. Set to `false` to disable. | + +### Startup / Shutdown Commands + +| Variable | Default | Description | +|----------|---------|-------------| +| `COMMAND_INIT` | — | Command to run on container startup. The last init command runs in the background to allow signal handling. | +| `COMMAND_INIT01`..`COMMAND_INIT99` | — | Additional numbered init commands, executed in order after `COMMAND_INIT`. | +| `COMMAND_EXIT` | — | Command to run on container shutdown (before processes are terminated). | +| `COMMAND_EXIT01`..`COMMAND_EXIT99` | — | Additional numbered exit commands, executed in order after `COMMAND_EXIT`. | + +### Logging + +| Variable | Default | Description | +|----------|---------|-------------| +| `LOG_FILE` | `/dev/null` | Path to a log file to tail. When set, the container's stdout will stream this file. | + +### Mirrors (China) + +| Variable | Default | Description | +|----------|---------|-------------| +| `USE_CHINA_MIRRORS` | `false` | Switch apt, pip, and npm to Aliyun mirrors on startup. | + +### Package Updates + +| Variable | Default | Description | +|----------|---------|-------------| +| `UPDATE_APT` | `false` | Run `apt update` on startup (with network check). | + +## Usage Examples + +Basic: +```bash +docker run -d ghcr.io/ahkhan03/ubuntu-24.04 +``` + +With a startup command and SSH: +```bash +docker run -d -p 2222:22 \ + -e COMMAND_INIT="echo 'hello from init'" \ + ghcr.io/ahkhan03/ubuntu-24.04 +``` + +Multiple init/exit commands: +```bash +docker run -d \ + -e COMMAND_INIT01="echo 'first'" \ + -e COMMAND_INIT02="python3 -m http.server 8080" \ + -e COMMAND_EXIT01="echo 'shutting down'" \ + ghcr.io/ahkhan03/ubuntu-24.04 +``` + +Without SSH, with China mirrors: +```bash +docker run -d \ + -e ENABLE_SSH=false \ + -e USE_CHINA_MIRRORS=true \ + ghcr.io/ahkhan03/ubuntu-24.04 +``` + +## Building + +```bash +./build.sh +``` + +See `./build.sh --help` for configuration options. diff --git a/build.sh b/build.sh index 0f4c4e4..e65e1ab 100755 --- a/build.sh +++ b/build.sh @@ -3,8 +3,10 @@ set -e # Configuration -REGISTRY="${REGISTRY:-gitea.ahkhan.me}" -REGISTRY_PATH="${REGISTRY_PATH:-docker}" +REGISTRY="${REGISTRY:-gitea2.ahkhan.me}" # pushed through gitea2 because gitea is behind CF tunnel and has issues with large image pushes. +REGISTRY_PATH="${REGISTRY_PATH:-packages}" +GITHUB_REGISTRY="${GITHUB_REGISTRY:-ghcr.io}" +GITHUB_USER="${GITHUB_USER:-ahkhan03}" REPO_PREFIX="${REPO_PREFIX:-ubuntu}" PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" DATE_TAG=$(date +%Y-%m-%d) @@ -43,15 +45,18 @@ build_ubuntu_version() { log "Building Ubuntu ${version}..." - # Build tags for this version + # Build tags for this version (Gitea + GitHub) local tags=( "${REGISTRY}/${REGISTRY_PATH}/${repo_name}:latest" "${REGISTRY}/${REGISTRY_PATH}/${repo_name}:${DATE_TAG}" + "${GITHUB_REGISTRY}/${GITHUB_USER}/${repo_name}:latest" + "${GITHUB_REGISTRY}/${GITHUB_USER}/${repo_name}:${DATE_TAG}" ) - + # Add ubuntu:latest tag only for the latest version if [[ "$version" == "$LATEST_VERSION" ]]; then tags+=("${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest") + tags+=("${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}:latest") fi # Build tag arguments @@ -124,7 +129,8 @@ validate_setup() { # Function to show build summary show_summary() { log "Build Summary:" - echo "Registry: $REGISTRY" + echo "Gitea registry: $REGISTRY/$REGISTRY_PATH" + echo "GitHub registry: $GITHUB_REGISTRY/$GITHUB_USER" echo "Date tag: $DATE_TAG" echo "Platforms: $PLATFORMS" echo "Ubuntu versions: ${UBUNTU_VERSIONS[*]}" @@ -132,11 +138,14 @@ show_summary() { echo "Images that will be built:" for version in "${UBUNTU_VERSIONS[@]}"; do - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:buildcache (cache)" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}-${version}:latest" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}-${version}:${DATE_TAG}" + echo " Cache: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:buildcache" if [[ "$version" == "$LATEST_VERSION" ]]; then - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}:latest" fi echo "" done @@ -169,10 +178,13 @@ main() { log "Available images:" for version in "${UBUNTU_VERSIONS[@]}"; do - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:latest" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}-${version}:${DATE_TAG}" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}-${version}:latest" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}-${version}:${DATE_TAG}" done - echo " ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest (→ Ubuntu ${LATEST_VERSION})" + echo " Gitea: ${REGISTRY}/${REGISTRY_PATH}/${REPO_PREFIX}:latest (→ Ubuntu ${LATEST_VERSION})" + echo " GitHub: ${GITHUB_REGISTRY}/${GITHUB_USER}/${REPO_PREFIX}:latest (→ Ubuntu ${LATEST_VERSION})" } # Help function @@ -182,10 +194,12 @@ show_help() { echo "Usage: $0 [OPTIONS]" echo "" echo "Environment Variables:" - echo " REGISTRY Docker registry (default: gitea.ahkhan.me)" - echo " REGISTRY_PATH Registry path (default: docker)" - echo " REPO_PREFIX Repository prefix (default: ubuntu)" - echo " PLATFORMS Target platforms (default: linux/amd64,linux/arm64)" + echo " REGISTRY Gitea registry (default: gitea.ahkhan.me)" + echo " REGISTRY_PATH Gitea registry path (default: docker)" + echo " GITHUB_REGISTRY GitHub registry (default: ghcr.io)" + echo " GITHUB_USER GitHub username (default: ahkhan03)" + echo " REPO_PREFIX Repository prefix (default: ubuntu)" + echo " PLATFORMS Target platforms (default: linux/amd64,linux/arm64)" echo "" echo "Examples:" echo " REGISTRY=myregistry.com ./build.sh" diff --git a/scripts/bin/configure-china-mirrors b/scripts/bin/configure-china-mirrors index b230370..dc358a9 100644 --- a/scripts/bin/configure-china-mirrors +++ b/scripts/bin/configure-china-mirrors @@ -8,10 +8,16 @@ set -e echo "Configuring Chinese mirrors (Aliyun) for apt, pip, and npm..." # Replace Ubuntu sources with Aliyun mirror +# Ubuntu 24.04+ uses DEB822 format in sources.list.d/ubuntu.sources if [[ -f /etc/apt/sources.list.d/ubuntu.sources ]]; then sudo sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list.d/ubuntu.sources sudo sed -i 's|http://security.ubuntu.com/ubuntu/|https://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list.d/ubuntu.sources - echo "Updated Ubuntu apt sources to use Aliyun mirrors" + echo "Updated Ubuntu apt sources (DEB822 format) to use Aliyun mirrors" +# Ubuntu 22.04 and older use the traditional sources.list format +elif [[ -f /etc/apt/sources.list ]]; then + sudo sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirrors.aliyun.com/ubuntu|g' /etc/apt/sources.list + sudo sed -i 's|http://security.ubuntu.com/ubuntu|https://mirrors.aliyun.com/ubuntu|g' /etc/apt/sources.list + echo "Updated Ubuntu apt sources (sources.list format) to use Aliyun mirrors" fi # Configure npm registry to use Chinese mirror (npmmirror.com is the recommended mirror) diff --git a/scripts/bin/setup-user-home b/scripts/bin/setup-user-home index 1800856..30bee1c 100644 --- a/scripts/bin/setup-user-home +++ b/scripts/bin/setup-user-home @@ -3,14 +3,19 @@ # Setup home directory for the current user # Useful for attaching vscode with container -set -e - user_name=$(whoami) -user_home="/home/$user_name" + +# Root's home is /root, not /home/root +if [[ "$user_name" == "root" ]]; then + user_home="/root" +else + user_home="/home/$user_name" +fi echo "Setting up home directory for user: $user_name" sudo mkdir -p "$user_home" sudo chown -R "$(id -u):$(id -g)" "$user_home" -cp -r /etc/skel/. "$user_home" 2>/dev/null || true +# Use -n (no-clobber) to avoid overwriting existing dotfiles (e.g. from mounted volumes) +cp -rn /etc/skel/. "$user_home" 2>/dev/null || true echo "Home directory setup completed: $user_home" diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 1f2fe79..ac0e89c 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -36,7 +36,7 @@ term_handler() { # Kill any still-running background processes if they didn't shut down gracefully if [[ -n "$INIT_PID" ]]; then if kill -0 "$INIT_PID" 2>/dev/null; then - echo "Init process still running, force killing: $INIT_PID" + echo "Init process still running, sending SIGTERM: $INIT_PID" kill "$INIT_PID" 2>/dev/null else echo "Init process already terminated gracefully" @@ -49,9 +49,11 @@ term_handler() { kill "$TAIL_PID" 2>/dev/null fi - # Stop SSH service - echo "Stopping SSH service..." - sudo service ssh stop 2>/dev/null || true + # Stop SSH service if it was started + if [[ "${ENABLE_SSH:-true}" == "true" || "$ENABLE_SSH" == "1" ]]; then + echo "Stopping SSH service..." + sudo service ssh stop 2>/dev/null || true + fi echo "Cleanup completed, exiting..." exit 0 @@ -75,8 +77,13 @@ if [[ $LOG_FILE != "/dev/null" ]]; then sudo chown -R "$(id -u):$(id -g)" "$LOG_FILE" fi -echo "Starting SSH service..." -sudo service ssh start +# Start SSH service unless explicitly disabled +if [[ "${ENABLE_SSH:-true}" == "true" || "$ENABLE_SSH" == "1" ]]; then + echo "Starting SSH service..." + sudo service ssh start +else + echo "SSH service disabled (ENABLE_SSH=$ENABLE_SSH)" +fi # Run initialization commands (last one in background to allow signal handling) # First collect all defined COMMAND_INIT variables