# How to Run OfficeCLI in CI/CD Docker Environments: Best Practices Guide

> Learn best practices for running OfficeCLI in CI/CD Docker environments. Discover multi-stage builds, version pinning, and writable /tmp volumes for seamless integration.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: best-practices
- Published: 2026-08-05

---

**The best practice for running OfficeCLI in CI/CD Docker environments is to use a multi-stage build with the official installer script, pin a specific version, and mount a writable `/tmp` volume for configuration fallback when running as non-root.**

OfficeCLI is distributed as a lightweight native binary designed specifically for containerized workflows. Its runtime includes built-in container detection and automatic configuration path fallback, making it ideal for CI/CD pipelines. This guide covers the implementation patterns used in the iOfficeAI/OfficeCLI repository to ensure reliable, secure deployments.

## Container-Aware Runtime Design

OfficeCLI detects its execution environment automatically without requiring manual configuration. Understanding these mechanisms helps you design robust CI/CD pipelines.

### Automatic Container Detection

The core library identifies container environments through multiple signals. In [`UpdateChecker.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/UpdateChecker.cs), the `IsInContainer` method checks:

- Common environment variables for Kubernetes, AWS Lambda, and Cloud Run
- Docker marker file at `/.dockerenv`
- Podman marker file at `/.containerenv`

```csharp
// Source: UpdateChecker.cs#L580-L595
// Detection logic runs automatically on startup

```

This detection enables container-specific behavior without user intervention.

### Read-Only Filesystem Handling

When `$HOME` is not writable—a common scenario in hardened CI containers—OfficeCLI falls back automatically. The `ConfigPathCandidates` property in [`UpdateChecker.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/UpdateChecker.cs) defines the search order:

```csharp
// Source: UpdateChecker.cs#L73-L78
// Falls back to /tmp when home directory is read-only

```

This guarantees startup success regardless of filesystem permissions.

## Recommended CI/CD Implementation

Follow these five practices derived from the official repository's CI workflow in `.github/workflows/build.yml#L44-L52`.

### 1. Pin Exact Versions

Avoid the `latest` endpoint in production pipelines. The [`install.sh`](https://github.com/iOfficeAI/OfficeCLI/blob/main/install.sh) script includes a `resolve_version` function that converts tags to immutable references:

```bash

# Source: install.sh#L27-L46

# Pinning prevents race conditions during releases

```

Specify a concrete version like `v1.4.3` in your build arguments.

### 2. Use the Official Installer with Checksum Verification

The [`install.sh`](https://github.com/iOfficeAI/OfficeCLI/blob/main/install.sh) script performs SHA-256 verification identical to the self-updater:

```bash

# Source: install.sh#L20-L38

# Downloads from primary mirror with GitHub fallback

# Verifies checksum before marking executable

```

This eliminates supply chain risks from manual downloads.

### 3. Implement Multi-Stage Builds

Separate download and runtime stages to minimize image size:

```dockerfile

# ---------- Build stage ----------

FROM alpine:3.20 AS downloader
ARG VERSION=v1.4.3          # Pin a concrete version

WORKDIR /tmp

# Use the official installer script (runs curl, checksum verification)

RUN apk add --no-cache curl ca-certificates && \
    curl -fsSL https://raw.githubusercontent.com/iOfficeAI/OfficeCLI/main/install.sh -o install.sh && \
    sh install.sh && \
    mv /tmp/officecli /usr/local/bin/officecli && \
    chmod +x /usr/local/bin/officecli

# ---------- Runtime stage ----------

FROM alpine:3.20
COPY --from=downloader /usr/local/bin/officecli /usr/local/bin/officecli

# Optional: create a writable cache directory for the fallback config

RUN mkdir -p /tmp/officecli-cache && chmod 777 /tmp/officecli-cache
ENV XDG_CACHE_HOME=/tmp/officecli-cache   # forces the /tmp fallback

ENTRYPOINT ["officecli"]

```

The final image contains only the verified binary—no build tools, no installer script.

### 4. Configure Writable Config Paths

For non-root users with read-only home directories, explicitly set the cache directory:

```dockerfile
ENV XDG_CACHE_HOME=/tmp/officecli-cache

```

Alternatively, mount a volume at runtime:

```bash
docker run -v $HOME/.cache/officecli:/tmp officecli:latest

```

This aligns with OfficeCLI's automatic `/tmp` fallback behavior.

### 5. Run as Non-Root User

The binary requires no privileges. Add to your Dockerfile:

```dockerfile
RUN adduser -D -u 1000 officecliuser
USER officecliuser

```

Container detection continues functioning correctly without root access.

## GitHub Actions Integration Example

The repository's own CI demonstrates the pattern in [`build.yml`](https://github.com/iOfficeAI/OfficeCLI/blob/main/build.yml):

```yaml

# Source: build.yml#L44-L52

# Publishes binary, then runs Docker smoke test

```

Adapt this for any Docker-based platform:

```yaml

# .github/workflows/officecli-job.yml

name: OfficeCLI Workflow
on: [push]

jobs:
  process-documents:
    runs-on: ubuntu-latest
    container:
      image: alpine:3.20
    steps:
      - name: Download and verify OfficeCLI
        run: |
          curl -fsSL https://raw.githubusercontent.com/iOfficeAI/OfficeCLI/main/install.sh | VERSION=v1.4.3 sh
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      
      - name: Run OfficeCLI commands
        run: officecli --version
        env:
          XDG_CACHE_HOME: /tmp

```

GitLab CI, Azure Pipelines, and other platforms follow identical patterns.

## Security Considerations

- **Supply chain integrity**: The installer script's checksum verification matches the self-updater logic, ensuring consistency across installation methods.
- **Minimal attack surface**: Multi-stage builds strip build-time dependencies from production images.
- **No secrets in images**: Configuration fallback to `/tmp` avoids embedding credentials in image layers.

## Summary

- OfficeCLI automatically detects containers via [`UpdateChecker.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/UpdateChecker.cs) environment checks and marker files
- Read-only `$HOME` directories trigger automatic fallback to `/tmp` through `ConfigPathCandidates`
- Pin exact versions using the `resolve_version` logic in [`install.sh`](https://github.com/iOfficeAI/OfficeCLI/blob/main/install.sh) to avoid mutable reference risks
- Use multi-stage builds to keep images minimal while preserving checksum verification
- Set `XDG_CACHE_HOME` or mount volumes for non-root users in hardened CI environments
- Run as non-root without losing container detection capabilities

## Frequently Asked Questions

### Does OfficeCLI require root privileges to run in Docker?

No. The binary has no privileged requirements and detects containers correctly regardless of user permissions. The `IsInContainer` method in [`UpdateChecker.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/UpdateChecker.cs) checks system markers accessible to any user. Running as non-root is recommended for security in CI/CD pipelines.

### What happens if my CI container has a read-only filesystem?

OfficeCLI handles this automatically. When the home directory is not writable, the configuration path logic in `UpdateChecker.cs#L73-L78` falls back to `/tmp`. You can also explicitly set `XDG_CACHE_HOME` to control the fallback location.

### How do I verify the OfficeCLI binary wasn't tampered with during download?

Use the official [`install.sh`](https://github.com/iOfficeAI/OfficeCLI/blob/main/install.sh) script, which implements SHA-256 checksum verification identical to the self-updater. The verification logic in `install.sh#L20-L38` downloads from the primary mirror with GitHub fallback, computes the hash, and compares against the published checksum before installation.

### Can I use OfficeCLI in Kubernetes or serverless containers like AWS Lambda?

Yes. The container detection in `UpdateChecker.cs#L580-L595` specifically recognizes Kubernetes, AWS Lambda, and Cloud Run environments through environment variable inspection. No additional configuration is required for these platforms.