diff --git a/docker/python-dev/Dockerfile b/docker/python-dev/Dockerfile index cce2b46..df170a8 100644 --- a/docker/python-dev/Dockerfile +++ b/docker/python-dev/Dockerfile @@ -1,17 +1,16 @@ FROM python:3.13 -ARG USERNAME=dev ARG UID=1000 ARG GID=1000 # Create user with sudo support -RUN groupadd --gid $GID $USERNAME \ - && useradd --uid $UID --gid $GID -m $USERNAME \ +RUN groupadd --gid $GID dev \ + && useradd --uid $UID --gid $GID -m dev \ && apt-get update \ && apt-get install -y sudo curl gnupg \ - && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME \ - && usermod -a -G dialout $USERNAME + && echo "dev ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/dev \ + && chmod 0440 /etc/sudoers.d/dev \ + && usermod -a -G dialout dev # Install system packages RUN apt-get install -y \ @@ -61,26 +60,32 @@ ENV LANG=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8 # Create user directories with proper ownership -RUN mkdir -p /home/${USERNAME}/.vscode-server/extensions \ - && mkdir -p /home/${USERNAME}/.local/bin \ - && mkdir -p /home/${USERNAME}/.claude \ +RUN mkdir -p /home/dev/.vscode-server/extensions \ + && mkdir -p /home/dev/.local/bin \ + && mkdir -p /home/dev/.claude \ && mkdir -p /workspace \ && mkdir -p /workspace/.venv \ - && chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.vscode-server \ - && chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.local \ - && chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.claude \ - && chown -R ${USERNAME}:${USERNAME} /workspace + && chown -R dev:dev /home/dev/.vscode-server \ + && chown -R dev:dev /home/dev/.local \ + && chown -R dev:dev /home/dev/.claude \ + && chown -R dev:dev /workspace VOLUME /workspace/.venv - - # Switch to non-root user (only once, for the rest of the build) -USER ${USERNAME} -WORKDIR /home/${USERNAME} +USER dev + +# create ssh keys +RUN ssh-keygen -q -t ed25519 -N "" -f /home/dev/.ssh/id_ed25519 && \ + printf "Host *\n StrictHostKeyChecking accept-new\n" > /home/dev/.ssh/config && \ + chmod 0700 /home/dev/.ssh && \ + chmod 0600 /home/dev/.ssh/id_ed25519 /home/dev/.ssh/config && \ + chmod 0644 /home/dev/.ssh/id_ed25519.pub + +WORKDIR /home/dev # Add local bin to PATH -ENV PATH="/home/${USERNAME}/.local/bin:${PATH}" +ENV PATH="/home/dev/.local/bin:${PATH}" # Install uv RUN curl -LsSf https://astral.sh/uv/install.sh | sh @@ -96,9 +101,9 @@ RUN curl -fsSL https://gh.io/copilot-install | bash RUN curl -fsSL https://claude.ai/install.sh | bash # User config (most frequently changed) -COPY --chown=${USERNAME}:${USERNAME} CLAUDE.md /home/${USERNAME}/.claude/CLAUDE.md -COPY --chown=${USERNAME}:${USERNAME} aliases.sh /home/${USERNAME}/.aliases.sh -COPY --chown=${USERNAME}:${USERNAME} bash_helpers.sh /home/${USERNAME}/.bash_helpers.sh +COPY --chown=dev:dev CLAUDE.md /home/dev/.claude/CLAUDE.md +COPY --chown=dev:dev aliases.sh /home/dev/.aliases.sh +COPY --chown=dev:dev bash_helpers.sh /home/dev/.bash_helpers.sh # Customize bash prompt RUN echo 'export PS1="${PROJECT_NAME:+\[\e[35m\][$PROJECT_NAME]\[\e[m\] }🐍 \[\e[33m\]\W\[\e[m\] \[\033[1;36m\]# \[\033[0m\]"' >> ~/.bashrc \ diff --git a/src/cli_tools/docker.py b/src/cli_tools/docker.py index dcffd81..677e244 100644 --- a/src/cli_tools/docker.py +++ b/src/cli_tools/docker.py @@ -1,6 +1,7 @@ """Docker image commands.""" import os +import subprocess import typer @@ -10,6 +11,7 @@ app = typer.Typer(help="Build and manage Docker images.", no_args_is_help=True) DOCKER_IMAGE = "python-dev" DOCKER_DIR = "docker/python-dev" +DOCKERHUB_IMAGE = "roxauto/python-dev" @app.command() @@ -30,3 +32,20 @@ def build( f"{'--no-cache ' if no_cache else ''}" f"--network=host {DOCKER_DIR}", ) + + +@app.command() +def push(tag: str = typer.Option("latest", help="Image tag.")): + """Tag and push the python-dev image to DockerHub.""" + token = os.environ.get("DOCKERHUB_TOKEN") + if not token: + typer.echo("DOCKERHUB_TOKEN env variable is not set.", err=True) + raise typer.Exit(1) + subprocess.run( + ["docker", "login", "-u", "roxauto", "--password-stdin"], + input=token, + text=True, + check=True, + ) + run(f"docker tag {DOCKER_IMAGE}:{tag} {DOCKERHUB_IMAGE}:{tag}") + run(f"docker push {DOCKERHUB_IMAGE}:{tag}")