PeiDocker Documentation¶
PeiDocker generates Docker configurations from YAML files to build reproducible Docker images without writing Dockerfiles directly.
Overview¶
PeiDocker provides: - Two-stage build system (stage-1 for system packages, stage-2 for applications) - CLI and web GUI interfaces - Automatic docker-compose.yml generation from user_config.yml - Storage strategy switching between volumes, host mounts, and in-image storage - Custom script execution at build, first-run, every-run, and user-login - SSH server configuration with multiple authentication methods - Environment variable substitution using Docker Compose syntax
Installation¶
From PyPI¶
pip install pei-docker
# For pixi users
pixi global install pipx
pipx install pei-docker
From Source¶
git clone https://github.com/igamenovoer/PeiDocker.git
cd PeiDocker
pip install -e .
Quick Start¶
Web GUI¶
# Start GUI with auto-selected port
pei-docker-gui start
# Specify port
pei-docker-gui start --port 8080
# Load existing project
pei-docker-gui start --project-dir /path/to/project
# Jump to specific configuration page
pei-docker-gui start --project-dir /path/to/project --jump-to-page ssh
# Native desktop mode (requires pywebview)
pei-docker-gui start --native
The GUI provides tabs for: - Project settings (base image, output naming) - SSH configuration (users, keys, authentication) - Network configuration (ports, proxy) - Storage management (volumes, bind mounts) - Script automation - Environment variables
Command Line¶
# Create new project
pei-docker-cli create -p /your/build/dir
# Generate docker-compose.yml
pei-docker-cli configure -p /your/build/dir
# Build images
cd /your/build/dir
docker compose build stage-1 --progress=plain
docker compose build stage-2 --progress=plain
# Run container
docker compose up stage-2
# SSH into container (if configured)
ssh me@127.0.0.1 -p 2222
Project Structure¶
project_dir/
├── user_config.yml # Main configuration file
├── docker-compose.yml # Generated by configure command
├── stage-1.Dockerfile # Generated stage-1 Dockerfile
├── stage-2.Dockerfile # Generated stage-2 Dockerfile
├── compose-template.yml # Template file (do not modify)
└── installation/ # Copied to /pei-from-host in image
├── stage-1/
│ ├── custom/ # Custom scripts for stage-1
│ ├── tmp/ # Downloaded packages
│ └── system/ # System configuration files
└── stage-2/
├── custom/ # Custom scripts for stage-2
├── tmp/ # Downloaded packages
└── system/ # System configuration files
Configuration Reference¶
Two-Stage Build System¶
- stage-1: Base image with system packages installed via apt
- stage-2: Application image built on stage-1 with custom packages
Storage Strategy¶
Stage-2 provides three directories with dynamic storage:
- /soft/app: Application installations
- /soft/data: Data files
- /soft/workspace: Working files
These symlink to either:
- /hard/volume/xxx: When external volume is mounted
- /hard/image/xxx: When using in-image storage
Storage types:
- auto-volume: Docker manages volume automatically
- manual-volume: User-specified volume name
- host: Bind mount from host directory
- image: Store inside Docker image
SSH Configuration¶
ssh:
enable: true
port: 22 # Container SSH port
host_port: 2222 # Host mapped port
users:
username:
password: 'pass'
uid: 1000 # Optional, auto-assigned if not set
# Choose one authentication method:
pubkey_file: 'path/to/key.pub' # Public key file
pubkey_text: 'ssh-rsa AAAA...' # Inline public key
privkey_text: '-----BEGIN...' # Inline private key
privkey_file: 'path/to/private.key' # Private key file
Script Execution Hooks¶
Scripts execute at four stages:
- on_build: During image build
- on_first_run: First container start
- on_every_run: Every container start
- on_user_login: User SSH login
Scripts support parameters:
on_build:
- 'script.sh --param=value --flag'
Environment Variables¶
Supports Docker Compose variable substitution:
environment:
- 'VAR_NAME=value'
- 'API_URL=${API_URL:-http://localhost:8080}'
Port Mapping¶
Separate port configurations for each stage:
stage_1:
ports:
- "5432:5432" # Database ports
stage_2:
ports:
- "8080:8080" # Application ports
Proxy Configuration¶
proxy:
address: host.docker.internal
port: 7890
enable_globally: false # Apply to all shell commands
remove_after_build: false # Remove after build
use_https: false # Use HTTPS proxy
APT Repository¶
apt:
repo_source: 'tuna' # Or: 'aliyun', '163', 'ustc', 'cn'
keep_repo_after_build: true
use_proxy: false
keep_proxy_after_build: false
CLI Commands¶
create¶
Creates new PeiDocker project.
pei-docker-cli create -p DIRECTORY [OPTIONS]
Options:
- -p, --project-dir: Project directory (required)
- -e, --with-examples: Include example files (default: true)
- --with-contrib: Include contrib directory (default: true)
configure¶
Generates docker-compose.yml from user_config.yml.
pei-docker-cli configure [OPTIONS]
Options:
- -p, --project-dir: Project directory (default: current)
- -c, --config: Config file name (default: user_config.yml)
- -f, --full-compose: Generate extended compose file
- --with-merged: Generate merged.Dockerfile, merged.env, and build-merged.sh for building without docker compose
Build Without Docker Compose (Merged Build)¶
If you prefer a single docker build flow without docker compose:
# Generate merged artifacts
pei-docker-cli configure --with-merged
# Build the final stage-2 image using merged.Dockerfile and merged.env
./build-merged.sh
# Override output image name:tag on the fly
./build-merged.sh --output-image myorg/myapp:dev
./build-merged.sh -o myorg/myapp:dev
This produces:
- merged.Dockerfile: stand-alone multi-stage Dockerfile (stage-1 + stage-2)
- merged.env: all build-time args as KEY='value'
- build-merged.sh: one-shot build script that sources merged.env and runs docker build
- Supports --output-image/-o <name:tag> to override the final image tag
Complete Configuration Example¶
stage_1:
image:
base: ubuntu:24.04
output: myapp:stage-1
ssh:
enable: true
port: 22
host_port: 2222
users:
me:
password: '123456'
uid: 1000
apt:
repo_source: ''
keep_repo_after_build: true
proxy:
address: host.docker.internal
port: 7890
enable_globally: false
environment:
- 'STAGE=development'
ports:
- "5432:5432"
device:
type: cpu
mount:
apt_cache:
type: auto-volume
dst_path: /var/cache/apt
custom:
on_build:
- 'stage-1/custom/setup.sh'
stage_2:
image:
base: null # Uses stage-1 output
output: myapp:stage-2
storage:
app:
type: auto-volume
data:
type: host
host_path: /data
workspace:
type: auto-volume
mount:
home_me:
type: auto-volume
dst_path: /home/me
custom:
on_build:
- 'stage-2/custom/install.sh'
Troubleshooting¶
Docker Registry Connection Issues¶
If unable to connect to docker.io:
# Pull base image manually
docker pull ubuntu:24.04
# Tag with local name
docker tag ubuntu:24.04 local-ubuntu:24.04
# Use local-ubuntu:24.04 in user_config.yml
Converting to docker run¶
Use Decomposerize to convert docker-compose.yml to docker run commands.
Persistent Changes¶
For on_first_run scripts, commit the container after first run to save changes:
docker commit <container_id> <new_image_name>