DCLint (Docker Compose Linter)

repository·main·Indexed 43 days ago

https://github.com/zavoloklom/docker-compose-linter

A command-line tool for validating and enforcing best practices in Docker Compose files. DCLint version 3.1.0 helps identify syntax errors, enforce style guidelines, and catch common configuration pitfalls. It supports automatic fixing via the --fix flag, custom configuration files (.dclintrc, dclint.config.js), and integrates with GitHub Actions, GitLab CI, pre-commit hooks, and MegaLinter.

Tokens
19K
Snippets
71
Records
94
Agent score
54%

What's inside DCLint

  1. Understand mandatory error checks in docker-compose-linter

    main

    Before applying any specific linting rules, docker-compose-linter performs mandatory structural checks. If these checks fail, the linter will stop and report an error to prevent analyzing improperly structured files.

    There are two primary mandatory error categories:

    1. Invalid YAML: Occurs when the target file is not a valid YAML document.
    2. Invalid Schema: Occurs when the YAML is valid, but does not conform to the expected Docker Compose schema structure.
  2. Control exit codes with --max-warnings

    main

    By default, any error causes a non-zero exit code. You can also configure the CLI to fail if the number of warnings exceeds a specific threshold using --max-warnings <number>.

    • Setting --max-warnings -1 (the default) disables the warning limit.
    • If the number of warnings exceeds the specified value, the command exits with a failure status.
    # Fail if there are more than 5 warnings
    npx dclint docker-compose.yml --max-warnings 5
  3. Use the require-quotes-in-ports rule

    main

    The require-quotes-in-ports rule ensures that port values in the ports and expose sections of a Docker Compose file are enclosed in quotes. This prevents YAML parsing errors, specifically the issue where YAML interprets xx:yy formats as base-60 values if the container port is lower than 60.

    This rule is fixable: the linter can automatically add the required quotes.

    Rule Details:

    • Rule Name: require-quotes-in-ports
    • Type: warning
    • Category: best-practice
    • Severity: minor
    • Fixable: true
    # Correct usage with single quotes
    services:
      foo:
        image: image
        ports:
          - '80:80'
          - '443:443'
        expose:
          - '3000'
  4. Understand the no-duplicate-exported-ports rule

    main

    The no-duplicate-exported-ports rule ensures that each service in a Docker Compose configuration exports unique ports on the host machine. If multiple services attempt to bind to the same host port, Docker Compose will fail to start. This rule is categorized as a critical security error and is not fixable automatically, as it requires manual resolution of the port conflicts.

    # Rule Metadata
    # Name: no-duplicate-exported-ports
    # Type: error
    # Category: security
    # Severity: critical
    # Fixable: false
  5. How YAML anchors are handled in DCLint

    main

    DCLint supports YAML anchors for schema validation, allowing you to reuse configuration sections.

    Limitations:

    • Anchors are not validated by individual linting rules.
    • Anchors are not automatically fixed when using the --fix flag.

    Best Practice: When using multiple anchors, use the YAML merge syntax to combine them in a single line rather than multiple separate lines. This is more compatible with Docker Compose limitations.

    Recommended Syntax:

    x-anchor1: &anchor1
      ports:
        - 80
    x-anchor2: &anchor2
      ports:
        - 81
    
    services:
      image: image
      <<: [ *anchor1, *anchor2 ]
  6. Understand DCLint rule severity and capabilities

    main

    DCLint uses specific indicators to communicate the impact and nature of a rule violation:

    • 🔴 Error: A critical issue. If this rule is violated, the linter will return a non-zero exit code.
    • 🟡 Warning: A non-critical issue. The linter will report the issue but the exit code will remain zero.
    • 🔧 Auto-fixable: The issue can be automatically corrected by the linter.
    • ⚙️ Configurable: The behavior of the rule can be adjusted via configuration options.
  7. Understand the no-version-field rule

    main

    The no-version-field rule enforces the removal of the version field from Docker Compose files.

    Rationale

    In modern Docker Compose, the version field is deprecated. Docker Compose now automatically determines the specification version based on the features used in the file. Removing this field promotes cleaner configurations and follows current best practices.

    Rule Metadata

    • Rule Name: no-version-field
    • Type: error
    • Category: best-practice
    • Severity: minor
    • Fixable: true

    When to avoid this rule

    Do not use this rule if you are working with legacy versions of Docker Compose that still require an explicit version field to function correctly.

    ### Problematic Code Example
    ```yaml
    version: '3.8'
    services:
      web:
        image: image

    Correct Code Example

    services:
      web:
        image: image
  8. Understand the no-quotes-in-volumes rule

    main

    The no-quotes-in-volumes rule ensures that values in the volumes section of services in a Docker Compose file are not enclosed in quotes. Quoted paths can cause unexpected behavior in Docker, such as incorrect mounting or path interpretation.

    This rule is categorized as a style rule with info severity and is emitted as a warning. It is fixable, meaning the linter can automatically remove the quotes from volume paths without changing the paths themselves.

    # Problematic Code Example
    services:
      foo:
        image: image
        volumes:
          - "/data:/app/data"
          - "logs:/app/logs"
  9. Use the service-image-require-explicit-tag rule

    main

    The service-image-require-explicit-tag rule ensures that services in Docker Compose files use specific version tags rather than ambiguous tags like latest, stable, or no tag at all. This prevents unpredictable behavior caused by image updates.

    Note: This rule is not fixable automatically because the linter cannot know which specific version you intend to use.

    # Correct usage: specify an exact version
    services:
      web:
        image: nginx:1.21.0
  10. Understand the no-build-and-image rule

    main

    The no-build-and-image rule ensures that each service in a Docker Compose configuration uses either the build directive or the image directive, but not both. Using both simultaneously can cause ambiguity and unpredictable behavior during container creation.

    Rule Metadata:

    • Rule Name: no-build-and-image
    • Type: error
    • Category: best-practice
    • Severity: major
    • Fixable: false (requires manual intervention to decide which directive to keep).

    Rationale:

    • build specifies building from a Dockerfile.
    • image specifies using a pre-built image from a registry.
    • If both are present without a pull_policy, Compose may attempt to pull the image first and then build from source if the image is missing, leading to unexpected deployment behavior.
  11. Limitation: Duplicate ports using environment variables

    main

    The no-duplicate-exported-ports rule cannot detect port conflicts when ports are defined using environment variables. Because environment variables are resolved at runtime, the linter cannot statically determine their values.

    Example of undetected conflict: If ${APP_PORT} resolves to 8080 at runtime, this configuration will cause a conflict that the linter will not catch:

    services:
      web:
        image: image
        ports:
          - "${APP_PORT}:80"
      db:
        image: image
        ports:
          - "8080:80"

    Recommendation: Manually verify that any environment variables used in the ports directive are unique across your services.

  12. Understand the `no-unbound-port-interfaces` rule

    main

    The no-unbound-port-interfaces rule is a security-focused rule that flags Docker Compose services where ports are specified without an explicit host interface or IP address.

    By default, if you only specify container_port:host_port, Docker binds the port to all network interfaces (0.0.0.0). This can unintentionally expose sensitive services (like databases) to the public internet or local network. To fix this, you should prefix the port mapping with a specific IP address, such as 127.0.0.1.

    Rule Metadata:

    • Name: no-unbound-port-interfaces
    • Type: error
    • Category: security
    • Severity: major
    • Fixable: false