# Dockerfile Linter — Security & best-practices checker (`perryay/dockerfile-linter-checker`) Actor

Lint Dockerfiles and docker-compose files against 15+ security and best-practice rules. Detects running as root, missing USER directive, unpinned packages, missing HEALTHCHECK, and more. Supports strict mode and batch linting.

- **URL**: https://apify.com/perryay/dockerfile-linter-checker.md
- **Developed by:** [Perry AY](https://apify.com/perryay) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.02 / dockerfile lint

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 🐳 Dockerfile Linter — Security & Best-Practices Checker

**Automated Dockerfile and docker-compose linter that enforces 21 security and quality rules out of the box — from containers running as root to missing HEALTHCHECK directives, unpinned package versions, and insecure COPY patterns. Integrates into any CI/CD pipeline with a strict mode that can gate deployments on ERROR-level findings.**

Modern container workflows move fast, but fast shouldn't mean fragile. Every Dockerfile and docker-compose configuration that ships to production carries implicit security and operational decisions — which base image to use, whether the container runs as root, how dependencies are installed, and whether the orchestrator can health-check the service. The Dockerfile Linter automates the review of these decisions across 21 rules (14 for Dockerfiles, 7 for docker-compose), producing structured findings with severity levels, remediation suggestions, and a quantitative pass score. No more relying on manual code reviews to catch container misconfigurations.

Designed for DevSecOps teams, platform engineers, and CI/CD pipelines, the linter accepts Dockerfile content directly, reads from a file path, or fetches from a URL or Apify Key-Value Store. It produces machine-readable JSON output suitable for downstream processing — dashboarding, alerting, or automated rollback gates. With strict mode enabled, any ERROR-level finding causes the run to fail, making it a drop-in quality gate for GitHub Actions, GitLab CI, Jenkins, or any CI/CD system that supports actor/webhook integration.

---

### What does it do?

The Dockerfile Linter analyses container build instructions against a comprehensive rule set derived from Docker best practices, CIS Docker Benchmark recommendations, and real-world production incidents. It operates in three modes — **Dockerfile-only**, **docker-compose-only**, or **both** — and returns a structured lint report for each.

For **Dockerfiles**, the linter scans every line for 14 distinct rules (coded DL3000–DL3015, excluding retired rules DL3012 and DL3014) covering base image tagging, user context, instruction choice (ADD vs COPY), multi-stage build hygiene, package manager discipline, and production-readiness checks like HEALTHCHECK. Rules are classified as ERROR, WARNING, or INFO so teams can triage findings by impact. The linter handles multi-stage builds intelligently — for example, DL3003 only flags a missing USER directive in the final stage, not in intermediate builder stages where root access may be legitimate.

For **docker-compose files**, the linter parses YAML service definitions and validates 7 policy rules (coded DC1000–DC1006) covering versioning, restart policies, resource limits, privileged mode, image tag pinning, health check configuration, and volume type decisions. Each service is checked independently, so a multi-service compose file gets per-service findings.

Every lint run produces a **Pass Score** on a 0–100 scale. ERROR-level findings deduct 20 points each, WARNING-level findings deduct 5 points each, and INFO findings are advisory only. A score of 70 or above is considered passing. When **strict mode** is enabled, the presence of any ERROR finding causes the run to report as failed — ideal for CI/CD gates where zero-tolerance policies apply.

---

### Who is it for?

| Persona | Why this actor matters |
|---|---|
| **DevSecOps Engineer** | Enforce security baselines across every container image built in the organisation. Block PRs with root containers or unpinned base images before they merge. |
| **Platform / SRE Engineer** | Ensure every service in the platform has HEALTHCHECK, resource limits, and restart policies defined. Catch `privileged: true` usage before it reaches production. |
| **Software Engineer** | Get instant feedback on Dockerfile quality during development. Learn best practices through structured remediation suggestions without memorising rule numbers. |
| **CI/CD Pipeline Architect** | Drop the actor into any pipeline (GitHub Actions, GitLab CI, Jenkins, Argo Workflows) as a quality gate. Use the JSON output for dashboards, Slack alerts, or automated rollback decisions. |
| **Container Security Auditor** | Batch-audit Dockerfiles across microservices repositories in a single run. Generate compliance evidence for CIS Docker Benchmark adherence. |
| **DevOps Onboarding Lead** | Standardise container configuration quality across teams. The linter serves as an automated code reviewer that never misses a best-practice check. |

---

### Why use this?

- **21 rules, zero configuration** — Rules cover the OWASP Docker security cheat sheet, CIS Docker Benchmark Level 1 & 2 controls, and community best practices. No config files to write, no plugin installs, no registry setup.
- **CI/CD-ready strict mode** — Flip `strictMode: true` and the actor fails on any ERROR finding. Integrates with GitHub Actions, GitLab CI, Jenkins, CircleCI, and Argo Workflows in minutes.
- **Quantitative pass scoring** — Every run produces a 0–100 score so you can trend quality over time, compare across teams, and set progressive quality targets (e.g., "all services must score ≥ 85").
- **Structured, machine-readable output** — Findings include rule ID, severity, title, description, remediation advice, line number, and offending text. Use the JSON output to build custom dashboards, trigger alerts, or feed into Jira automation.
- **Multi-mode linting** — Lint Dockerfiles, docker-compose files, or both in a single run. Supports content pasted directly, file paths, or URL/KVS lookups.
- **Intelligent multi-stage analysis** — Rules that apply only to the final stage (root user check) are evaluated correctly, avoiding false positives on builder stages.
- **Remediation guidance built in** — Every finding includes actionable remediation text. Engineers don't need to search Stack Overflow to fix a DL3004 or DC1002 issue.
- **No vendor lock-in** — Runs on the Apify platform but the rule engine is pure Python with no proprietary dependencies. The actor's source is available and extensible.

---

### Features

#### Dockerfile Rules — DL3000 to DL3015 (14 checks)

| ID | Severity | Rule | What It Checks | Why It Matters |
|---|---|---|---|---|
| **DL3000** | 🔴 ERROR | Pin base image tags | `FROM python:latest` detected | `latest` changes silently — breaks reproducibility and can introduce breaking OS/package changes mid-release |
| **DL3001** | 🟠 WARNING | Add USER directive | No `USER` line found in the entire Dockerfile | Root containers are a top-10 container security risk. If compromised, the attacker has full host-level access (depending on runtime) |
| **DL3002** | 🟠 WARNING | Prefer COPY over ADD | `ADD` instruction used for local files | `ADD` has hidden behaviours (automatic tar extraction, remote URL fetching) that create opaque builds and potential security surprises |
| **DL3003** | 🔴 ERROR | No root user in final stage | Final build stage lacks a `USER` directive | Even if earlier stages have users, the final running image defaults to root unless explicitly switched. A common oversight in multi-stage builds |
| **DL3004** | 🟠 WARNING | Pin apt package versions | `apt-get install curl` (no `=version`) | Unpinned packages produce different results on different build dates. Pin versions for deterministic, auditable builds |
| **DL3005** | 🟠 WARNING | Combine apt-get update && install | Separate `RUN apt-get update` and `RUN apt-get install` | Separate instructions create an extra layer and risk caching a stale `apt-get update` while picking up newer packages — a security gap |
| **DL3006** | ℹ️ INFO | Remove apt lists after install | Missing `rm -rf /var/lib/apt/lists/*` | Leftover apt lists add significant bloat (50–100 MB per layer). Clean up in the same `RUN` instruction |
| **DL3007** | 🟠 WARNING | Avoid sudo in RUN | `RUN sudo ...` pattern detected | `sudo` inside a Dockerfile indicates the container is running as root *or* has inconsistent user switching. Either way, the permission model needs review |
| **DL3008** | 🟠 WARNING | Use WORKDIR not RUN cd | `RUN cd /app && ...` pattern | `RUN cd` only affects that single shell command. `WORKDIR` sets the working directory for all subsequent instructions and is self-documenting |
| **DL3009** | 🔴 ERROR | Add HEALTHCHECK instruction | No `HEALTHCHECK` found in the Dockerfile | Orchestrators (Kubernetes, Docker Swarm, ECS) rely on HEALTHCHECK for traffic routing and self-healing. Missing it means downtime isn't detected automatically |
| **DL3010** | ℹ️ INFO | Use COPY --chown | `COPY` without `--chown` flag | Setting ownership at copy time eliminates the need for a separate `RUN chown` layer, reducing image size and build time |
| **DL3011** | 🟠 WARNING | Name multi-stage build stages | `FROM ... AS` missing in multi-stage builds | Unnamed stages make the Dockerfile harder to read and prevent `--target` selective builds |
| **DL3013** | 🟠 WARNING | Use pip --no-cache-dir | `pip install` without `--no-cache-dir` | Pip cache adds 10–100 MB per layer. Add `--no-cache-dir` to keep images lean |
| **DL3015** | 🟠 WARNING | Use --no-install-recommends | `apt-get install` without `--no-install-recommends` | Recommends packages add substantial image bloat — often doubling the layer size for utility packages |

#### Docker-Compose Rules — DC1000 to DC1006 (7 checks)

| ID | Severity | Rule | What It Checks | Why It Matters |
|---|---|---|---|---|
| **DC1000** | ℹ️ INFO | Add version field | Compose file missing `version` | While recent Docker Compose v2 treats version as optional, specifying it ensures compatibility across different Docker Engine versions and CI runners |
| **DC1001** | 🟠 WARNING | Define restart policy | Service missing `restart` configuration | Without a restart policy, a crashed or OOM-killed service stays down until manually restarted. Production services should use `unless-stopped` or `always` |
| **DC1002** | 🟠 WARNING | Set resource limits | Service missing `deploy.resources.limits` | Unbounded services can consume all host memory or CPU, starving sibling containers and triggering OOM kills across the node |
| **DC1003** | 🔴 ERROR | Avoid privileged mode | Service has `privileged: true` | Privileged mode grants full host capabilities — device access, kernel namespace manipulation, and bypass of seccomp/AppArmor. Equivalent to running the container as root *on the host* |
| **DC1004** | 🟠 WARNING | Pin image tags | Service uses `image: myapp` or `:latest` | Unpinned images break rolling deployments — different nodes may pull different versions based on cache freshness |
| **DC1005** | 🟠 WARNING | Add healthcheck | Service missing `healthcheck` block | Docker Compose health checks enable dependency ordering (`depends_on` with condition) and provide status to orchestration layers |
| **DC1006** | ℹ️ INFO | Use named volumes | Bind mount (`./host/path:/container/path`) detected | Bind mounts tie the service to a specific host filesystem layout, preventing portability across environments and complicating backup strategies |

#### Pass Score System

Each lint run produces a **Pass Score** (0–100) that quantifies overall quality:

| Finding Type | Point Deduction | Interpretation |
|---|---|---|
| 🔴 ERROR | −20 points each | Critical security or reliability issue — must be fixed |
| 🟠 WARNING | −5 points each | Best-practice deviation — should be addressed |
| ℹ️ INFO | 0 points | Advisory — consider for long-term improvement |

**Score thresholds:**

- **Score ≥ 70** → Pass. Acceptable quality for most environments.
- **Score < 70** → Needs improvement. Review findings and remediate.
- **Any ERROR + Strict Mode** → Run fails immediately, regardless of score.

Examples:

- A Dockerfile with `FROM python:latest` (DL3000, ERROR), root user in final stage (DL3003, ERROR), missing HEALTHCHECK (DL3009, ERROR), and no `USER` directive (DL3001, WARNING) → score = 100 − 60 − 5 = **35 (Needs improvement)**
- The same file with five unpinned apt packages (DL3004, WARNING each) → score = 100 − 20 − 5 − 5 − 5 − 5 − 5 = **55 (Needs improvement)**
- A docker-compose file with `privileged: true` (DC1003, ERROR) in strict mode → score = 80 but run **fails** due to strict mode

#### Charge Events

The actor records platform usage through the following charge events:

| Event | When Charged |
|---|---|
| `dockerfile-lint` | Each Dockerfile lint operation |
| `compose-validate` | Each docker-compose validation operation |
| `policy-check` | Each strict-mode enforcement check |
| `batch-lint` | *(reserved)* Future batch-linting support |

---

### Input Parameters

| Field | Type | Default | Required | Description |
|---|---|---|---|---|
| `mode` | select | `dockerfile` | No | Lint scope: `dockerfile`, `compose`, or `both` |
| `dockerfileContent` | textarea | — | Yes* | Full content of the Dockerfile to lint. Paste directly or leave blank when using `dockerfilePath` |
| `dockerfilePath` | string | — | No | Alternative to `dockerfileContent` — path to a Dockerfile file on the same filesystem, a URL, or an Apify Key-Value Store key |
| `composeContent` | textarea | — | Yes** | Full content of the docker-compose.yml file to lint. Required when `mode` is `compose` or `both` |
| `strictMode` | boolean | `false` | No | When enabled, any ERROR-level finding causes the actor to report a failure (for CI/CD gate enforcement) |

\* Required unless `dockerfilePath` is provided and `mode` is `dockerfile` or `both`.
\** Required when `mode` is `compose` or `both`.

---

### Example Input

#### Example 1: Dockerfile Lint (mode: dockerfile)

```json
{
  "mode": "dockerfile",
  "dockerfileContent": "FROM python:latest\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\nCOPY . .\nCMD [\"python\", \"app.py\"]\n",
  "strictMode": true
}
````

#### Example 2: Dockerfile Lint with Path

```json
{
  "mode": "dockerfile",
  "dockerfilePath": "./path/to/Dockerfile",
  "strictMode": false
}
```

#### Example 3: Dockerfile Lint with URL

```json
{
  "mode": "dockerfile",
  "dockerfilePath": "https://raw.githubusercontent.com/example/repo/main/Dockerfile",
  "strictMode": true
}
```

#### Example 4: Docker-Compose Lint (mode: compose)

```json
{
  "mode": "compose",
  "composeContent": "services:\n  web:\n    image: nginx:latest\n    ports:\n      - \"80:80\"\n    privileged: true\n  api:\n    image: myapp\n    build: .\n",
  "strictMode": true
}
```

#### Example 5: Lint Both (mode: both)

```json
{
  "mode": "both",
  "dockerfileContent": "FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install\nCOPY . .\nCMD [\"node\", \"server.js\"]\n",
  "composeContent": "version: \"3.8\"\nservices:\n  app:\n    build: .\n    image: my-app:1.0.0\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n    deploy:\n      resources:\n        limits:\n          memory: \"512M\"\n          cpus: \"0.5\"\n",
  "strictMode": false
}
```

***

### Output Format

The actor pushes a single dataset item per run with the following structure:

```json
{
  "dockerfile": {
    "findings": [
      {
        "id": "DL3000",
        "severity": "ERROR",
        "title": "Use specific base image tags (not 'latest')",
        "description": "Base image uses 'latest' tag which leads to non-reproducible builds.",
        "remediation": "Pin to a specific version tag (e.g., python:3.13-slim instead of python:latest).",
        "line": 1,
        "text": "FROM python:latest"
      },
      {
        "id": "DL3003",
        "severity": "ERROR",
        "title": "No root user in final image",
        "description": "Final stage should switch to non-root user via USER directive.",
        "remediation": "Add 'USER nobody' or create a dedicated user at the end of your Dockerfile.",
        "line": null,
        "text": null,
        "stage": "final"
      },
      {
        "id": "DL3009",
        "severity": "ERROR",
        "title": "Add HEALTHCHECK instruction",
        "description": "Production containers should have a HEALTHCHECK for orchestration.",
        "remediation": "Add HEALTHCHECK instruction to your Dockerfile.",
        "line": null,
        "text": null
      },
      {
        "id": "DL3001",
        "severity": "WARNING",
        "title": "No USER directive found",
        "description": "Running containers as root is a security risk.",
        "remediation": "Add a USER directive to run as non-root user.",
        "line": null,
        "text": null
      }
    ],
    "errorCount": 3,
    "warningCount": 1,
    "infoCount": 0,
    "passScore": 35
  },
  "summary": {
    "totalErrors": 3,
    "totalWarnings": 1,
    "overallPassScore": 35,
    "reviewedAt": "2026-07-23T12:00:00"
  }
}
```

#### Output Field Reference

| Field | Type | Description |
|---|---|---|
| `dockerfile` / `compose` | object | Lint results for each mode that was run |
| `[].findings` | array | List of rule violations found |
| `[].findings[].id` | string | Rule identifier (e.g., `DL3000`, `DC1003`) |
| `[].findings[].severity` | string | `ERROR`, `WARNING`, or `INFO` |
| `[].findings[].title` | string | Short rule summary |
| `[].findings[].description` | string | Detailed explanation of the issue |
| `[].findings[].remediation` | string | Actionable fix suggestion |
| `[].findings[].line` | number or null | Line number in the Dockerfile (null for file-level checks) |
| `[].findings[].text` | string or null | Offending text excerpt (null for absence checks) |
| `[].findings[].service` | string or null | Service name for compose findings (null for Dockerfile rules) |
| `[].errorCount` | number | Total ERROR-level findings |
| `[].warningCount` | number | Total WARNING-level findings |
| `[].infoCount` | number | Total INFO-level findings |
| `[].passScore` | number | Pass score 0–100 for this mode |
| `summary.totalErrors` | number | Combined errors across all modes |
| `summary.totalWarnings` | number | Combined warnings across all modes |
| `summary.overallPassScore` | number | Overall pass score 0–100 |
| `summary.reviewedAt` | string | ISO 8601 timestamp of the lint run |

#### Dataset Views

The actor's dataset includes three pre-configured views for convenient analysis:

| View | Fields Included | Best For |
|---|---|---|
| **Overview** | Error/warning counts and pass scores across all modes | Dashboarding and trending |
| **Errors Only** | All ERROR-level findings with rule IDs and line numbers | Triage sessions and incident response |
| **Dockerfile Findings** | All Dockerfile-specific findings with line-level detail | Developer feedback in CI/CD |

***

### Use Cases

- **CI/CD Pipeline Quality Gate** — Plug the actor into GitHub Actions, GitLab CI, or Jenkins as a pre-deployment step. With strict mode enabled, any ERROR-level finding (root user, missing HEALTHCHECK, privileged compose service) blocks the pipeline and notifies the team. The pass score provides a quantitative quality metric that teams can target and trend over time.

- **Security Compliance Auditing** — Enforce CIS Docker Benchmark Level 1 and Level 2 recommendations across your entire container fleet. The linter's DL3001 (USER directive), DL3009 (HEALTHCHECK), and DC1003 (privileged mode) rules map directly to CIS controls. Use the structured output to generate compliance reports for internal audits or customer security questionnaires.

- **Multi-Repository Batch Audit** — When taking over a legacy codebase or preparing for a platform migration, run the linter against every Dockerfile across your microservice repositories. The pass score gives you an instant inventory of which services need attention, while individual findings tell engineers exactly what to fix. No need to clone and review each repo manually.

- **DevOps Onboarding & Standards Enforcement** — Standardise container configuration quality across teams by integrating the linter into your code review workflow. New team members learn best practices through structured remediation guidance rather than tribal knowledge. The linter catches common mistakes — FROM latest, missing HEALTHCHECK, unbounded compose resources — before they reach the reviewer's inbox.

- **Kubernetes Readiness Validation** — Ensure every container image destined for Kubernetes has proper HEALTHCHECK directives, runs as a non-root user, and uses pinned base images. The linter validates these requirements before the image is built and pushed to your registry, reducing the feedback loop from "CrashLoopBackOff in production" to "CI pipeline rejection in development."

- **Supply Chain Security Hardening** — Pin base image tags, apt package versions, and pip packages to prevent supply chain attacks where a compromised `latest` tag or unpinned dependency introduces malicious code into your build pipeline. The linter's DL3000, DL3004, and DL3013 rules target exactly these vectors.

- **Dockerfile Refactoring & Modernisation** — When migrating from single-stage to multi-stage builds or switching from Alpine to distroless base images, run the linter before and after the change to verify that best practices are maintained. The DL3003 (final stage root user) and DL3011 (multi-stage naming) rules catch common refactoring mistakes.

- **Cloud Migration & Containerisation Audits** — As part of a lift-and-shift or re-platforming migration, audit all newly created Dockerfiles for security and operability issues. The linter's comprehensive rule set serves as an automated checklist that ensures containerised applications meet production readiness standards before they reach the cloud environment.

# Actor input Schema

## `mode` (type: `string`):

Select what to lint: 'dockerfile' (Dockerfile only), 'compose' (docker-compose only), or 'both'

## `dockerfileContent` (type: `string`):

The full content of your Dockerfile to lint

## `dockerfilePath` (type: `string`):

Alternative to dockerfileContent: provide a URL or Apify KVS key to fetch the Dockerfile

## `composeContent` (type: `string`):

The full content of your docker-compose.yml file to lint

## `strictMode` (type: `boolean`):

When enabled, any ERROR-level finding is treated as a failure (for CI/CD gate enforcement)

## Actor input object example

```json
{
  "mode": "dockerfile",
  "dockerfileContent": "FROM python:3.13-slim\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\nCMD [\"python\", \"app.py\"]",
  "strictMode": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dockerfile/compose lint results in the default dataset — one item per run

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "dockerfileContent": `FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]`,
    "dockerfilePath": "",
    "composeContent": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("perryay/dockerfile-linter-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "dockerfileContent": """FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD [\"python\", \"app.py\"]""",
    "dockerfilePath": "",
    "composeContent": "",
}

# Run the Actor and wait for it to finish
run = client.actor("perryay/dockerfile-linter-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "dockerfileContent": "FROM python:3.13-slim\\nWORKDIR /app\\nCOPY requirements.txt .\\nRUN pip install --no-cache-dir -r requirements.txt\\nCOPY . .\\nCMD [\\"python\\", \\"app.py\\"]",
  "dockerfilePath": "",
  "composeContent": ""
}' |
apify call perryay/dockerfile-linter-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=perryay/dockerfile-linter-checker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Dockerfile Linter — Security & best-practices checker",
        "description": "Lint Dockerfiles and docker-compose files against 15+ security and best-practice rules. Detects running as root, missing USER directive, unpinned packages, missing HEALTHCHECK, and more. Supports strict mode and batch linting.",
        "version": "1.0",
        "x-build-id": "gdLFvqTKlhb2kCosJ"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/perryay~dockerfile-linter-checker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-perryay-dockerfile-linter-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/perryay~dockerfile-linter-checker/runs": {
            "post": {
                "operationId": "runs-sync-perryay-dockerfile-linter-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/perryay~dockerfile-linter-checker/run-sync": {
            "post": {
                "operationId": "run-sync-perryay-dockerfile-linter-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Lint Mode",
                        "enum": [
                            "dockerfile",
                            "compose",
                            "both"
                        ],
                        "type": "string",
                        "description": "Select what to lint: 'dockerfile' (Dockerfile only), 'compose' (docker-compose only), or 'both'",
                        "default": "dockerfile"
                    },
                    "dockerfileContent": {
                        "title": "Dockerfile Content",
                        "type": "string",
                        "description": "The full content of your Dockerfile to lint"
                    },
                    "dockerfilePath": {
                        "title": "Dockerfile Path (URL or Apify Key-Value Store)",
                        "type": "string",
                        "description": "Alternative to dockerfileContent: provide a URL or Apify KVS key to fetch the Dockerfile"
                    },
                    "composeContent": {
                        "title": "Docker-Compose Content",
                        "type": "string",
                        "description": "The full content of your docker-compose.yml file to lint"
                    },
                    "strictMode": {
                        "title": "Strict Mode",
                        "type": "boolean",
                        "description": "When enabled, any ERROR-level finding is treated as a failure (for CI/CD gate enforcement)",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
