Compare commits

..

24 Commits

Author SHA1 Message Date
68f0d2efc9 Fixes for Apple container.
All checks were successful
Build Docker Image / build (push) Successful in 16s
2025-12-21 22:14:21 +01:00
e6b4fdec1a Fixed issues with setting up colored Bash prompt supporting displaying Git repository information.
All checks were successful
Build Docker Image / build (push) Successful in 38s
2025-12-21 13:50:07 +00:00
b908f3f1f0 Fix: correct indentation in link-to-bin script 2025-12-19 16:47:16 +01:00
Sławomir Koszewski
4de8cc79f2 Fix: update file path associations in VSCode settings for additional scripts 2025-12-19 16:07:56 +01:00
1cbbe22dc1 Fix: correct file path associations in VSCode settings 2025-12-19 11:03:45 +01:00
42c2dd933c Fix: ensure git prompt helper is sourced in the default user's .bashrc
All checks were successful
Build Docker Image / build (push) Successful in 1m21s
2025-12-17 22:20:09 +01:00
Slawek Koszewski
b90a6a0746 Added a script that links "azure-cli" executable script to $HOME/bin. 2025-12-17 19:08:13 +01:00
c83a4f115a Fix: adopted volume list parsing for docker CLI.
All checks were successful
Build Docker Image / build (push) Successful in 11s
2025-12-17 07:59:19 +01:00
ca8160568b Fix: Corrected Git Prompt activation. 2025-12-17 07:58:45 +01:00
1d66fc2edc Remove unverified support for podman. 2025-12-16 10:14:48 +01:00
c078feceac Fix: formatting in README. 2025-12-16 09:57:47 +01:00
a155a48aaa Rewrite README to accomodate to changes to the script. 2025-12-16 09:57:01 +01:00
d2f8eaf090 Add build status badge to README.md 2025-12-16 09:44:22 +01:00
4178864d33 Fix paths in GitHub Actions workflow trigger for Docker build
All checks were successful
Build Docker Image / build (push) Successful in 11s
2025-12-16 09:42:27 +01:00
4d7ab9138d Update paths in GitHub Actions workflow trigger for Docker build 2025-12-16 09:41:42 +01:00
19f03f2c4c Fix environment variable reference for Docker Hub login in GitHub Actions workflow
All checks were successful
Build Docker Image / build (push) Successful in 50s
2025-12-16 09:39:12 +01:00
663b830dc4 Fix environment variable reference for Docker Hub login in GitHub Actions workflow
Some checks failed
Build Docker Image / build (push) Failing after 26s
2025-12-16 09:36:59 +01:00
89bc15a4a9 Add Docker Hub login and push steps to GitHub Actions workflow
Some checks failed
Build Docker Image / build (push) Failing after 33s
2025-12-16 09:24:21 +01:00
62b1e4c6ef Update GitHub Actions checkout action to version 6
All checks were successful
Build Docker Image / build (push) Successful in 11s
2025-12-16 09:10:58 +01:00
5723140bce Add GitHub Actions workflow for building Docker image
All checks were successful
Build Docker Image / build (push) Successful in 5s
2025-12-16 08:40:05 +01:00
6325017ba7 Change Bash prompt to utilize environment variable ACCOUNT_NAME. 2025-12-16 08:38:18 +01:00
65bbb79396 Added ACCOUNT_NAME variable to container's run environment. Streamline argument handling. 2025-12-16 08:37:51 +01:00
374b4e48bf Added an option to specify a custom volume name. 2025-12-15 09:02:33 +01:00
a40a96e662 Added a prompt to create a volume for an unknown account. 2025-12-15 08:17:58 +01:00
9 changed files with 200 additions and 86 deletions

View File

@@ -0,0 +1,30 @@
name: Build Docker Image
on:
push:
branches:
- main
paths:
- Dockerfile
- entrypoint.sh
- .gitea/workflows/build.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Build Docker image
run: |
docker build -t skoszewski/azure-cli:latest .
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Push Docker image to Docker Hub
run: |
docker push skoszewski/azure-cli:latest

View File

@@ -1,6 +1,8 @@
{
"files.associations": {
"/build": "shellscript",
"/azure-cli": "shellscript"
"./build": "shellscript",
"./azure-cli": "shellscript",
"./link-to-bin": "shellscript",
"./entrypoint.sh": "shellscript"
}
}

View File

@@ -18,23 +18,22 @@ RUN curl -sL -o /tmp/packages-microsoft-prod.deb https://packages.microsoft.com/
RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/repos/azure-cli/ noble main" > /etc/apt/sources.list.d/azure-cli.list
RUN apt-get update && apt-get install -y azure-cli
# Configure Bash
RUN cat <<'EOF' >> /etc/bash.bashrc
if [ -f /usr/lib/git-core/git-sh-prompt ]; then
source /usr/lib/git-core/git-sh-prompt
# Then PS1 can include __git_ps1 which is optimized and shows branch + state:
PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\[\e[33m\]$(__git_ps1 " (%s)")\[\e[0m\]\$ '
fi
export PATH=$HOME/bin:$PATH
EOF
# Add more packages (keep it last to optimize layer caching)
RUN apt-get install -y zip unzip tree wget nano neovim \
python3 python3-venv python3-pip
COPY enable-git-bash-prompt /usr/local/bin/enable-git-bash-prompt
# Patch the default .bashrc to enable git bash prompt
RUN cat <<'EOF' >> /etc/skel/.bashrc
# Enable git bash prompt
if [ -f /usr/local/bin/enable-git-bash-prompt ]; then
source /usr/local/bin/enable-git-bash-prompt
fi
EOF
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -1,20 +1,32 @@
# Azure CLI container
[![Build Status](https://gitea.koszewscy.waw.pl/slawek/azure-cli/actions/workflows/build.yml/badge.svg)](https://gitea.koszewscy.waw.pl/slawek/azure-cli/actions?workflow=build.yml)
This repository contains a Dockerfile for building an Azure CLI container image.
It is designed to be used as a operating environment for running Azure CLI commands,
while providing isolation from the host system. User's home directory is mounted
into the container to persist configuration and credentials. Volume is used to
while providing isolation from the host system. Volume is used to
persist home directory data.
## Usage
```bash
azure-cli [--account ACCOUNT_NAME] [--user CONTAINER_USERNAME] [ container CLI arguments... ]
```text
azure-cli (-l|--list)
```
- `--account ACCOUNT_NAME` - Specify the account name to use for the volume that stores the home directory data. Defaults to the current user's username.
- `--user CONTAINER_USERNAME` - Specify the username to use inside the container. Defaults `ubuntu`.
- `container CLI arguments...` - Any additional arguments are passed to the container CLI command (not the command inside the container).
List all containers created by this script.
> **Note:** Copy the `azure-cli` script to a directory in your `PATH` (e.g. `/usr/local/bin`) to use it as a regular command.
```text
azure-cli [(-a|--account) <account_name>]
[--user <user_name>]
[--name <container_name>]
[--volume <local_path>:<container_path>]
[--]
[ other arguments passed as a command to execute inside the container ]
```
- `--account <account_name>`: Specifies the account name to be set as an environment variable inside the container. The volume name will be derived from this account name.
- `--user <user_name>`: Specifies the user name to be used inside the container. Default is 'ubuntu'.
- `--name <container_name>`: Specifies the name of the container. Default is sanitized account name.
- `--volume <local_path>:<container_path>`: Binds additional local path to a path inside the container.
- `--`: Indicates the end of options for the script. Any arguments following this will be passed as a command to execute inside the container.

View File

@@ -2,16 +2,23 @@
# Set default values
ACCOUNT_NAME="$(id -un)"
USER_NAME="ubuntu"
USER_NAME="${USER_NAME:-ubuntu}"
EXTRA_ARGS=()
LIST=""
VOLUME_NAME=""
HOME_DIR="/home/${USER_NAME}"
# Parse command line arguments
while [ $# -gt 0 ]; do
case $1 in
--list|-l)
LIST=true
break
;;
--name|-n)
VOLUME_NAME="$2"
shift 2
;;
--account|-a)
ACCOUNT_NAME="$2"
shift 2
@@ -25,6 +32,11 @@ while [ $# -gt 0 ]; do
EXTRA_ARGS+=("--mount" "type=bind,source=${VOL_SRC},target=${VOL_DST}")
shift 2
;;
--root)
USER_NAME="root"
HOME_DIR="/root"
shift
;;
--)
# Stop parsing arguments
shift
@@ -33,10 +45,16 @@ while [ $# -gt 0 ]; do
--help|-h)
cat <<EOF
Usage: $(basename "$0")
[--list|-l]
or
[--account|-a ACCOUNT_NAME]
[--name|-n VOLUME_NAME]
[--user|-u USER_NAME]
[--volume|-v HOST_PATH:CONTAINER_PATH]
[additional docker/podman/container args]
[--]
[additional args to pass to container]
EOF
exit 0
;;
@@ -48,20 +66,20 @@ done
IMAGE_NAME="skoszewski/azure-cli:latest"
# Check if a custom volume name is provided
if [ -z "$VOLUME_NAME" ]; then
# Normalize account name for use in volume name
SANITIZED_ACCOUNT_NAME="${ACCOUNT_NAME/@/_at_}"
SANITIZED_ACCOUNT_NAME="${SANITIZED_ACCOUNT_NAME//[-.]/_}"
VOLUME_NAME="account_${ACCOUNT_NAME/@/_at_}"
VOLUME_NAME="${VOLUME_NAME//[-.]/_}"
fi
# Find container runtime
if command -v podman &> /dev/null; then
CMD="podman"
EXTRA_ARGS+=("--hostname $(hostname -s)")
if command -v container &> /dev/null; then
# Apple container command line tool
CMD="container"
elif command -v docker &> /dev/null; then
CMD="docker"
EXTRA_ARGS+=("--hostname $(hostname -s)")
elif command -v container &> /dev/null; then
# Apple container command line tool
CMD="container"
else
echo "Error: No usable container runtime was found." >&2
exit 1
@@ -69,28 +87,62 @@ fi
if [ -n "$LIST" ]; then
echo "Available accounts:"
# Unfortunately 'container' and 'docker' CLIs are not compatible
if [ "container" = "$CMD" ]; then
$CMD volume ls --format json | jq -r '.[] | select(.labels | has("account")) | .labels.account'
else
# Docker has settled to provide labels as one string, that's inconvinient
$CMD volume ls --format=json | jq -sr '.[] | .Account = (.Labels | match("account=([a-zA-Z0-9._%@+-]+)"; "x") | .captures[0].string) | .Account'
fi
exit 0
fi
if [ "container" = "$CMD" ]; then
_FOUND="$($CMD volume ls --format json | jq -r --arg name "$VOLUME_NAME" --arg account "$ACCOUNT_NAME" '.[] | select(.name == $name or .labels.account == $account) | "FOUND"')"
else
_FOUND="$($CMD volume ls --format=json | jq -sr --arg name "$VOLUME_NAME" --arg account "$ACCOUNT_NAME" '.[] | .Account = (.Labels | match("account=([a-zA-Z0-9._%@+-]+)"; "x") // {} | .captures[0].string) | select(.Name == $name or .Account == $account) | "FOUND"')"
fi
# Check, if the account volume exists, if not create it
# This ensures persistent storage for the Azure CLI configuration
if ! $CMD volume inspect "account_$SANITIZED_ACCOUNT_NAME" &> /dev/null; then
echo "Creating volume account_$SANITIZED_ACCOUNT_NAME for Azure CLI configuration."
if ! $CMD volume create "account_$SANITIZED_ACCOUNT_NAME" --label "account=$ACCOUNT_NAME" &> /dev/null; then
echo "Error: Failed to create volume account_$SANITIZED_ACCOUNT_NAME." >&2
if [ ! "FOUND" = "$_FOUND" ]; then
echo "A volume for account '$ACCOUNT_NAME' does not exist."
read -p "Would you like to create one? (y/n) " -r RESPONSE
if [[ ! "$RESPONSE" =~ ^[Yy]$ ]]; then
echo "Aborting."
exit 1
fi
echo "Creating volume $VOLUME_NAME for Azure CLI configuration."
if ! $CMD volume create "$VOLUME_NAME" --label "account=$ACCOUNT_NAME" &> /dev/null; then
echo "Error: Failed to create volume $VOLUME_NAME." >&2
exit 1
fi
# Volume created, initialize it
echo "Initializing volume $VOLUME_NAME."
if ! $CMD run --rm -it --mount "type=volume,source=$VOLUME_NAME,target=$HOME_DIR" $IMAGE_NAME; then
echo "Error: Failed to initialize volume $VOLUME_NAME." >&2
exit 1
fi
echo "Volume $VOLUME_NAME initialized successfully."
fi
EXTRA_ARGS+=(
"--mount" "type=volume,source=account_$SANITIZED_ACCOUNT_NAME,target=/home/${USER_NAME}"
"--mount" "type=volume,source=$VOLUME_NAME,target=/home/${USER_NAME}"
"--mount" "type=bind,source=$(pwd),target=/workdir"
"--env" "ACCOUNT_NAME=$ACCOUNT_NAME"
"--env" "USER_NAME=$USER_NAME"
"--env" "HOME_DIR=$HOME_DIR"
"--name" "azure-cli-$VOLUME_NAME"
"--workdir" "/workdir"
)
# Run the container
$CMD run --rm -it \
${EXTRA_ARGS[@]} \
--name "azure-cli-$SANITIZED_ACCOUNT_NAME" \
--workdir /workdir \
$IMAGE_NAME --user "$USER_NAME" "$@"
if [ "$USER_NAME" != "root" ]; then
EXTRA_ARGS+=(
"--user" "$USER_NAME"
)
fi
# Run the container as the specified user
$CMD run --rm -it ${EXTRA_ARGS[@]} $IMAGE_NAME "$@"

12
build
View File

@@ -1,17 +1,13 @@
#!/usr/bin/env bash
# Find container runtime
if command -v podman &> /dev/null; then
CMD="podman"
elif command -v docker &> /dev/null; then
CMD="docker"
if command -v docker &> /dev/null; then
echo "Using Dokcer as container runtime."
docker buildx build -t skoszewski/azure-cli:latest .
elif command -v container &> /dev/null; then
# Apple container command line tool
CMD="container"
container build -t skoszewski/azure-cli:latest .
else
echo "Error: No usable container runtime was found." >&2
exit 1
fi
echo "Using container runtime: $CMD"
$CMD build -t skoszewski/azure-cli:latest .

7
enable-git-bash-prompt Normal file
View File

@@ -0,0 +1,7 @@
# Include Git prompt helpers if available
if [ -f /usr/lib/git-core/git-sh-prompt ]; then
source /usr/lib/git-core/git-sh-prompt
# Then PS1 can include __git_ps1 which is optimized and shows branch + state:
PS1='\[\e[32m\]AzureCLI (\[\e[35m\]${ACCOUNT_NAME}\[\e[0m\])\n\[\e[0m\]\[\e[34m\]\w\[\e[0m\]\[\e[33m\]$(__git_ps1 " (%s)")\[\e[0m\]\$ '
fi

View File

@@ -2,42 +2,41 @@
set -e
# Let's set some defaults
SU_USER="ubuntu"
# Setup default values
USER_NAME="${USER_NAME:-ubuntu}"
HOME_DIR="${HOMED_DIR:-/home/${USER_NAME}}"
# Parse command line arguments
while [ $# -gt 0 ]; do
case "$1" in
-u|--user)
SU_USER="$2"
shift 2
;;
*)
break
;;
esac
done
# Check if the user exists
if ! id -u "$SU_USER" >/dev/null 2>&1; then
useradd -m -s /usr/bin/bash "$SU_USER"
fi
# Check if the home directory exists
if [ ! -d "/home/$SU_USER" ]; then
echo "A home directory for $SU_USER does not exist. Exiting."
# Check, if we are running as root
if [ "$(id -u)" -eq 0 ]; then
# Check, if the home directory exists for the specified user
if [ ! -d "$HOME_DIR" ]; then
echo "Error: Home directory for user '${USER_NAME}' does not exist." >&2
exit 1
fi
# Check user ownership of the home directory
if [ "$(stat -c '%u' /home/$SU_USER)" -ne "$(id -u $SU_USER)" ]; then
# Change ownership of the home directory
chown $SU_USER:$SU_USER /home/$SU_USER
echo "Preparing home directory for user '${USER_NAME}' at '${HOME_DIR}'."
# Check, ownership of the home directory
if [ "$(stat -c '%u' "$HOME_DIR")" -eq 0 ]; then
# The home directory is a fresh volume owned by root, change ownership
echo "Changing ownership of home directory to user '${USER_NAME}'."
chown "${USER_NAME}:${USER_NAME}" "$HOME_DIR"
fi
# Switch to the specified user
if [ $# -gt 0 ]; then
exec su $SU_USER -c "$@"
else
exec su $SU_USER
if [ "$USER_NAME " != "root" ]; then
# Re-initialize the contents of the home directory
su - "${USER_NAME}" -c "cp -a /etc/skel/. $HOME_DIR"
# We are done as root, quit. The container will be re-run as the specified user.
exit 0
fi
fi
# Verify that we are running as the user owning the home directory
if [ "$(id -un)" != "${USER_NAME}" ]; then
echo "Error: The script must be run as user '${USER_NAME}'." >&2
exit 1
fi
# Run shell
exec /usr/bin/bash "$@"

17
link-to-bin Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/bash
#
# Make a symbolic link from the 'azure-cli' executable script
# to $HOME/bin.
#
if [ ! -d "$HOME/bin" ]; then
mkdir -p "$HOME/bin"
cat <<'EOF' >> $HOME/.bashrc
# Add $HOME/bin to the PATH variable
export PATH=$HOME/bin:$PATH
EOF
fi
# Make a link
ln -s "$(cd $(dirname ${BASH_SOURCE[0]}); pwd)/azure-cli" "$HOME/bin/azure-cli"