Skip to content

deviantony/pctl

Repository files navigation

pctl - Dev Companion for Portainer

A simple CLI tool for quickly deploying and re-deploying your application on a Portainer environment.

asciicast

Usage

Prerequisites

  • A docker-compose.yml file in your project directory
  • Portainer instance with API access
  • Portainer API token (generate in Portainer: Settings > API Keys)

1. Initialize Configuration

pctl init

Interactive setup to configure your Portainer connection (URL, API token, environment). This creates a pctl.yml configuration file.

2. Deploy Your Application

pctl deploy

Deploy your Docker Compose stack to Portainer. The tool reads your docker-compose.yml file and creates a new stack.

Build Support: If your compose file contains build: directives, pctl will automatically build the images before deployment. See the Build Configuration section for details.

3. Update Existing Stack

pctl redeploy

Update an existing stack with latest images.

Force Rebuild: Use the -f or --force-rebuild flag to force rebuild images even if they haven't changed:

pctl redeploy -f

This sets force_build=true for this run, which includes no-cache behavior, ensuring a complete rebuild of all images.

4. Check Status

pctl ps

View stack status and running containers.

5. View Logs

pctl logs

Stream real-time logs from your containers.

Log Options:

  • -t, --tail N: Show the last N lines from the end of logs (default: 50)
  • -s, --service NAME: Show logs from a specific service only
  • --non-interactive: Force non-interactive mode (useful for testing and automation)

Examples:

# Show last 100 lines from all containers
pctl logs -t 100

# Show logs from a specific service
pctl logs -s web

# Show last 20 lines from the database service
pctl logs -s database -t 20

# Force non-interactive mode (useful for testing)
pctl logs --non-interactive

# Non-interactive mode with specific service and tail count
pctl logs -s web -t 10 --non-interactive

6. Check Version

pctl version

Display version information including version number, git commit hash, build timestamp, Go version, and target platform.

Configuration

pctl uses a pctl.yml configuration file created during initialization:

portainer_url: https://portainer.example.com
api_token: ptr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
environment_id: 1
stack_name: pctl_myproject
compose_file: docker-compose.yml
skip_tls_verify: true

The configuration includes:

  • portainer_url: Your Portainer instance URL
  • api_token: Portainer API token (starts with ptr_)
  • environment_id: Portainer environment ID
  • stack_name: Name for your stack in Portainer
  • compose_file: Path to your Docker Compose file
  • skip_tls_verify: Skip TLS verification for self-hosted instances

Build Configuration

When using build: directives in your compose file, pctl can automatically build images before deployment. Add a build section to your pctl.yml:

build:
  mode: remote-build        # remote-build (default) or load
  parallel: auto            # concurrent builds (auto or number)
  tag_format: "pctl-{{stack}}-{{service}}:{{hash}}"
  platforms: ["linux/amd64"]  # for load mode
  extra_build_args: {}      # global build args
  force_build: false        # force rebuild even if unchanged
  warn_threshold_mb: 50     # warn if context > 50MB

Build Modes

  • remote-build (default): Builds images on the remote Docker engine via Portainer's Docker proxy. Most bandwidth-efficient.
  • load: Builds images locally and uploads them to the remote engine. Useful when the remote has poor internet access.

Example Compose with Build

version: '3.8'
services:
  web:
    build:
      context: ./web
      dockerfile: Dockerfile
      args:
        NODE_ENV: production
    ports:
      - "3000:3000"
  
  api:
    build: ./api
    ports:
      - "8080:8080"

When you run pctl deploy, it will:

  1. Detect the build: directives
  2. Build the images according to your build configuration
  3. Transform the compose file to use the built images
  4. Deploy the stack to Portainer

Installation

Download the latest release for your platform from GitHub Releases:

Linux AMD64

wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_amd64.tar.gz
tar -xzf pctl_1.2.2_linux_amd64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/

Linux ARM64

wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_arm64.tar.gz
tar -xzf pctl_1.2.2_linux_arm64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/

macOS AMD64

wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_amd64.tar.gz
tar -xzf pctl_1.2.2_darwin_amd64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/

macOS ARM64 (Apple Silicon)

wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_arm64.tar.gz
tar -xzf pctl_1.2.2_darwin_arm64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/

Windows AMD64

wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_windows_amd64.zip
# Extract the zip file and move pctl.exe to your PATH

Testing

pctl includes both unit tests and integration tests to ensure reliability and correctness.

Unit Tests

Run the unit test suite:

# Run all unit tests
make test

# Run tests with coverage report
make test-coverage

Unit tests cover:

  • Configuration loading and validation
  • Compose file parsing and transformation
  • Build system components (tagging, context handling, orchestration)
  • Portainer API client functionality
  • Error handling and formatting

Integration Tests

Integration tests run against a real Portainer instance to validate end-to-end functionality.

Prerequisites:

  • Access to a Portainer instance
  • Portainer API token
  • Valid environment ID in Portainer

Setup:

  1. Copy the example configuration:
cp integration_test_config.json.example integration_test_config.json
  1. Edit integration_test_config.json with your Portainer details:
{
  "portainer_url": "https://your-portainer-instance.com",
  "api_token": "ptr_your_api_token_here",
  "environment_id": 1
}

Running Integration Tests:

# Run integration tests
make test-integration

Integration tests cover:

  • Deploying simple stacks (images only)
  • Redeploying existing stacks
  • Force rebuild with -f flag
  • Stack status checking (pctl ps)
  • Container logs (pctl logs)
  • Build functionality (both remote-build and load modes)
  • Error handling for non-existent stacks

Note: Integration tests will create and clean up test stacks automatically. The tests use unique stack names to avoid conflicts.

Development

Creating Releases

Releases are automated using GoReleaser and GitHub Actions. To create a new release:

# Create a new release (e.g., version 1.1.1)
./scripts/release.sh 1.1.1

# Dry run to see what would happen
./scripts/release.sh 1.1.1 --dry-run

This will:

  1. Create a git tag v1.1.1
  2. Push the tag to GitHub
  3. GoReleaser automatically builds binaries for all platforms
  4. Creates a GitHub release with all binaries, checksums, and release notes

See RELEASE.md for detailed release process documentation.

Limitations

  • Docker Standalone environments only - Full support for Kubernetes environments is planned for future versions.

About

A dev companion ! Deploy and re-deploy your app to Portainer using the CLI

Resources

License

Stars

Watchers

Forks

Packages

No packages published