Sobes.tech
Middle

What are the best practices for using ADD and COPY instructions in Docker?

sobes.tech AI

Answer from AI

There are several best practices for ADD and COPY instructions in Docker aimed at improving security, transparency, and build efficiency.

The main difference between ADD and COPY:

  • COPY simply copies files and directories from the specified source on the host to the specified destination in the container. The source must be a local file or directory.
  • ADD has broader capabilities: it can copy local files and directories, as well as extract archives (tar, gzip, bzip2) and fetch files from URLs.

Best practices:

  1. Prefer COPY over ADD: In most cases, COPY is sufficient. It is more transparent as it simply copies local files. Using ADD for extracting archives or downloading from URLs can be less predictable and increase build complexity.

  2. Use COPY for local files: If you need to copy files from the build context into the image, always use COPY.

    # Instead of ADD . /app
    COPY . /app 
    
  3. Be cautious with URLs in ADD: Using ADD with URLs can lead to build instability if the remote resource is unavailable. It can also be less secure as it depends on external sources. Prefer using curl or wget in a separate layer (RUN) to download resources from URLs, which provides more control and allows checksum verification.

    # Instead of ADD http://example.com/file.tar.gz /tmp/
    RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* \
        && curl -fsSL http://example.com/file.tar.gz -o /tmp/file.tar.gz \
        && tar -xzf /tmp/file.tar.gz -C /app \
        && rm /tmp/file.tar.gz
    
  4. Extract archives in a separate layer when using ADD: If you must use ADD to extract an archive (less common scenario), ensure you do it in a separate layer. However, as mentioned earlier, more explicit extraction using RUN is often preferable.

  5. Copy only necessary files: Do not copy the entire build context (COPY . /app) if it contains unnecessary files (source code, test data, hidden directories, etc.). Use .dockerignore to exclude these files. This reduces image size and speeds up build by decreasing data transferred to the Docker daemon.

    Example .dockerignore:

    .git
    node_modules
    *.log
    tmp/
    
    # Copy only necessary files after applying .dockerignore
    COPY . /app
    
  6. Use absolute paths for destinations: Always specify absolute destination paths in the image (/app, /usr/local/bin, etc.). This makes the Dockerfile more understandable and predictable, avoiding ambiguity regarding the current working directory (WORKDIR).

    # Always specify absolute destination paths
    COPY src /app/src
    
  7. Vary the order based on change frequency: Place COPY or ADD instructions for files that change less frequently (e.g., dependency files like package.json, requirements.txt) higher in the Dockerfile than instructions for files that change more often (application source code). This allows Docker to efficiently use layer caching.

    # Dependency files (change less often)
    COPY requirements.txt /app/
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Application source code (change more often)
    COPY . /app/ 
    

Summary table:

Instruction Description Recommended use What to avoid
COPY Copies local files/directories Copying local files and directories into the image. Using it when you need to extract archives or download from URLs.
ADD Copies local files/directories, extracts archives, downloads from URL Use for automatic archive extraction (rare). Using it for copying local files (prefer COPY). Using it for URL downloads.

Following these practices results in more reliable, secure, and efficient Docker images.