---
title: First instruction must be ARG or FROM
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > First instruction must be ARG or FROM
---

# First instruction must be ARG or FROM

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `dockerfile-first-instruction-should-be-arg-or-from` 

**Platform:** Dockerfile

**Severity:** Medium

**Category:** Best Practices

#### Learn More{% #learn-more %}

- [Provider Reference](https://docs.docker.com/engine/reference/builder/#from)

### Description{% #description %}

Dockerfiles must start with either an `ARG` or `FROM` instruction, because the initial instruction defines the base image and the scope of build-time variables. Placing another instruction first can result in unintended base images, mis-scoped build arguments, and unpredictable build-time behavior that increases supply-chain and configuration risks.

This rule inspects `dockerfile_container` resources and flags cases where the earliest parsed instruction is not `ARG` or `FROM`.

To remediate, ensure the first non-comment line in the Dockerfile is an `ARG` (when build-time variables must be substituted into `FROM`) or a `FROM` instruction that explicitly defines the base image.

Secure examples:

```dockerfile
# ARG before FROM to allow substitution in the base image
ARG BASE_IMAGE=alpine:3.16
FROM ${BASE_IMAGE}
```

```dockerfile
# Direct FROM as the first instruction
FROM ubuntu:22.04
```

## Compliant Code Examples{% #compliant-code-examples %}

```dockerfile
# Negative case 1: Starting with ARG (correct - can precede FROM)
ARG foo

FROM nginx:${foo:-1.25}-alpine AS builder

LABEL maintainer="web-team@example.com"
LABEL description="Nginx static site builder with proper first instruction"

# Set build arguments
ARG BUILD_DATE
ARG VERSION=1.0.0

LABEL build_date="${BUILD_DATE}"
LABEL version="${VERSION}"

# Install build tools
RUN apk add --no-cache \
    nodejs \
    npm \
    git

WORKDIR /build

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci

# Copy source code
COPY . .

# Build static site
RUN npm run build

# Production stage
FROM nginx:1.25-alpine

LABEL maintainer="web-team@example.com"
LABEL description="Production Nginx static site"

# Install runtime dependencies
RUN apk add --no-cache \
    curl \
    tzdata

# Negative case 2: RUN command after FROM (correct order)
RUN something

# Remove default nginx config
RUN rm -rf /usr/share/nginx/html/*

# Copy built site from builder
COPY --from=builder --chown=nginx:nginx /build/dist /usr/share/nginx/html

# Copy custom nginx configuration
COPY --chown=nginx:nginx nginx.conf /etc/nginx/nginx.conf
COPY --chown=nginx:nginx default.conf /etc/nginx/conf.d/default.conf

# Create necessary directories
RUN mkdir -p /var/cache/nginx /var/log/nginx && \
    chown -R nginx:nginx /var/cache/nginx /var/log/nginx && \
    chmod -R 755 /var/cache/nginx

# Expose ports
EXPOSE 80 443

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/health || exit 1

# Switch to non-root user
USER nginx

# Start nginx
CMD ["nginx", "-g", "daemon off;"]
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```dockerfile
# Positive case 1: Starting with COPY instead of FROM or ARG (incorrect)
COPY foo bar

RUN command

FROM nginx:1.25-alpine

LABEL maintainer="web-team@example.com"
LABEL description="Nginx static site with incorrect first instruction"

# Install additional tools
RUN apk add --no-cache \
    curl \
    bash

WORKDIR /usr/share/nginx/html

ADD foo bar

# Copy website files
COPY --chown=nginx:nginx ./dist /usr/share/nginx/html

# Copy nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf

# Create cache directory
RUN mkdir -p /var/cache/nginx && \
    chown -R nginx:nginx /var/cache/nginx

# Expose HTTP and HTTPS ports
EXPOSE 80 443

USER nginx

CMD ["nginx", "-g", "daemon off;"]
```
