首先创建一个 docker-ubuntu 目录,在这个目录下创建 Dockerfile 文件以及 docker-enter.sh 脚本。我这里拉取的基础镜像为ubuntu:20.04,拉取的是官方的镜像,有可能会失败,需要挂VPN或者使用国内的镜像源。

使用方法:直接 ./docker-enter.sh 运行脚本,会自动安装镜像以及创建一个Ubuntu容器。还会在容器里克隆一个与你主机用户信息一样的一个普通用户,以及把你主机用户的家目录挂载到容器的 /home/hosthome 目录下,方便操作文件而不会改变文件的权限。

后续进入容器也可以通过运行脚本进入,默认登录的是普通用户,./docker-enter.sh root 登录的是root用户。内容如下:

Dockerfile:

# 基础镜像
FROM ubuntu:20.04

# 避免 tzdata 交互
ENV DEBIAN_FRONTEND=noninteractive

# 切换 apt 镜像源
RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|http://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list

# 安装常用工具
RUN apt-get update && apt-get install -y \
    sudo \
    vim \
    git \
    curl \
    locales \
    tzdata \
    python3 \
    python3-pip \
    build-essential \
    cmake \
    g++-multilib \
    && rm -rf /var/lib/apt/lists/*

# 生成 UTF-8 locale
RUN locale-gen en_US.UTF-8

# 全局默认环境变量(构建期)
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

# 在 /etc/profile 里再设置一遍,保证所有用户登录 shell 都有 UTF-8
RUN echo 'export LANG=en_US.UTF-8'     >> /etc/profile && \
    echo 'export LANGUAGE=en_US:en'     >> /etc/profile && \
    echo 'export LC_ALL=en_US.UTF-8'    >> /etc/profile

# 默认主机用户信息(可被 docker run 覆盖)
ENV HOST_USER=dev
ENV HOST_UID=1000
ENV HOST_GID=1000

# 创建用户脚本(容器启动时执行)
RUN echo '#!/bin/bash\n\
if ! id "$HOST_USER" &>/dev/null; then\n\
    groupadd -g $HOST_GID $HOST_USER\n\
    useradd -m -s /bin/bash -u $HOST_UID -g $HOST_GID $HOST_USER\n\
    echo "$HOST_USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers\n\
fi\n\
exec su - $HOST_USER' > /startup.sh \
    && chmod +x /startup.sh

# 默认启动脚本
CMD ["/startup.sh"]

docker-enter.sh:

#!/bin/bash
set -e

IMAGE_NAME="ubuntu20.04-dev"
CONTAINER_NAME="ubuntu20.04-dev-container"

# 默认进入 user,传参为 root 则进入root用户
TARGET_USER="$USER"
if [[ "$1" == "root" ]]; then
    TARGET_USER="root"
fi

echo "➡ 目标用户:$TARGET_USER"

# 检查 docker 是否可用
if ! command -v docker &>/dev/null; then
    echo "❌ 未找到 docker 命令,请确认已安装 Docker 并在当前用户下可用。"
    exit 1
fi

# 检查镜像是否存在,不存在就构建
if ! docker images --format '{{.Repository}}' | grep -qx "$IMAGE_NAME"; then
    echo "🔧 镜像不存在,正在构建..."
    docker build -t "$IMAGE_NAME" .
else
    echo "✔ 镜像已存在,跳过构建。"
fi

# 检查容器是否存在
if docker ps -a --format '{{.Names}}' | grep -qx "$CONTAINER_NAME"; then
    echo "✔ 容器已存在。"

    # 如果容器没在运行,则启动它
    if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME")" != "true" ]; then
        echo "▶ 启动容器..."
        docker start "$CONTAINER_NAME"
    fi

    echo "➡ 进入容器 (${TARGET_USER}) ..."
    docker exec -it --user "$TARGET_USER" "$CONTAINER_NAME" bash

else
    echo "🚀 创建并运行容器..."

    # 第一次创建容器时:
    # - 不在镜像名后面加 bash,使用 Dockerfile 里的 CMD ["/startup.sh"]
    # - /startup.sh 会根据 HOST_USER / HOST_UID / HOST_GID 创建用户并 su 过去
    docker run -it --name "$CONTAINER_NAME" \
        -v "$HOME":/home/hosthome \
        -e HOST_USER="$USER" \
        -e HOST_UID="$(id -u)" \
        -e HOST_GID="$(id -g)" \
        "$IMAGE_NAME"
fi

更多推荐