Exciting news! TCMS official website is live! Offering full-stack software services including enterprise-level custom R&D, App and mini-program development, multi-system integration, AI, blockchain, and embedded development, empowering digital-intelligent transformation across industries. Visit dev.tekin.cn to discuss cooperation!

Dockerfile Multiline File Writing: Full Compatibility Solutions for Legacy Docker Versions

2026-04-05 6 mins read

This article comprehensively summarizes 4 practical methods to write multi-line configurations and scripts to files in a Dockerfile, with a focus on the incompatibility of the syntax=docker/dockerfile:1 heredoc syntax in legacy Docker (v0) versions. Based on locally tested and validated approaches including RUN { ... }|tee, echo $'...', printf, and backslash line continuation ...

Writing multi-line scripts and configuration files directly into containers is a frequent operation in Docker image building. However, many developers encounter common issues: the modern syntax=docker/dockerfile:1 heredoc syntax fails to work in legacy Docker (v0) versions, leading to line break errors, variable exceptions, and permission loss.

This article features locally tested, stable writing methods that do not rely on advanced syntax and are compatible with all Docker versions. It compiles a set of the most practical, secure, and production-ready solutions for multi-line file writing.

Many tutorials recommend the heredoc syntax as follows:

# syntax=docker/dockerfile:1
RUN <<EOF cat > file.sh
...
EOF

This approach has critical drawbacks:

  1. Docker BuildKit must be enabled; the syntax is completely ignored in legacy Docker (v0) versions, causing build failures.
  2. Incompatibility with some CI/CD pipelines and private image registries.
  3. Despite good readability, it has extremely poor cross-environment compatibility.

Conclusion: For stability and universal compatibility, traditional RUN syntax is a must—and it is the core focus of this article.

II. 4 Standard, Fully Compatible Methods for Multiline File Writing in Dockerfile

All methods below have been locally tested and validated with no compatibility issues, and can be copied and used directly.

Ideal for complete shell scripts with clear structure, easy maintenance, and no escape character headaches.

RUN { \
        echo '#!/bin/sh'; \
        echo 'set -eu'; \
        echo; \
        echo 'if [ -L "/app/sentry/node_modules" ]; then'; \
        echo '    rm -f /app/sentry/node_modules'; \
        echo 'fi'; \
        echo 'ln -s /app/sentry_deps/node_modules /app/sentry/node_modules'; \
        echo 'exec "$@"'; \
    } | tee /app/entrypoint.sh && chmod +x /app/entrypoint.sh

Advantages:

  • Independent echo for each line, intuitive and error-resistant.
  • Supports blank lines, comments, and complex logic.
  • Compatible with all Docker versions.
  • tee outputs content to the console simultaneously for easy debugging.

2. For Short Configurations: echo $'...' with \n Line Breaks

Suitable for small configuration files such as .ini / .conf / .yaml:

RUN echo $'[section]\n\
key=value\n\
another_key=another_value' > /etc/my_config.ini
  • $'...' natively recognizes \n as line breaks.
  • The line continuation backslash \ must be at the end of the line with no trailing spaces.

3. For Precise Formatting: Multiline Writing with printf

Ideal for scenarios requiring strict control over line breaks and spaces:

RUN printf "user=root\n\
pass=123456\n\
host=127.0.0.1\n" > /etc/db.conf

4. For Long Scripts: Bulk Writing with echo $'...'

Suitable for writing complete logic scripts in a single block:

RUN echo $'#!/bin/sh\n\
set -eu\n\
if [ -L "/app/sentry/node_modules" ]; then\n\
    rm -f /app/sentry/node_modules\n\
fi\n\
exec "$@"' > /entrypoint.sh && chmod +x /entrypoint.sh

III. Core Knowledge and Pitfall Avoidance (Critical)

  1. No spaces after the line continuation backslash \—this will cause immediate build errors.
  2. Always add chmod +x to scripts; otherwise, they cannot be executed.
  3. Single quotes with echo 'a': output content as-is, no variable interpolation.
  4. Double quotes with echo "a$var: enable variable interpolation.
  5. > overwrites the target file; >> appends content to the target file.
  6. Add set -eu to multi-line scripts to improve robustness (abort on error/unset variable).
  7. Use -L to check for symbolic links and -d to check for directories.

IV. Production-Ready, Fully Buildable Dockerfile

FROM tekintian/alpine:3.12

ENV SENTRY_VERSION="8.26.0" \
    NODE_VERSION="8.17.0" \
    NODE_ENV=development

LABEL maintainer="tekintian@gmail.com"
LABEL version="${SENTRY_VERSION}"

WORKDIR /app

# Write entrypoint script (compatible with all Docker versions, most stable)
RUN { \
        echo '#!/bin/sh'; \
        echo 'set -eu'; \
        echo; \
        echo 'if [ -L "/app/sentry/node_modules" ]; then'; \
        echo '    echo "🗑️  Clean up old symlink"'; \
        echo '    rm -f /app/sentry/node_modules'; \
        echo 'fi'; \
        echo; \
        echo 'if [ -d "/app/sentry/node_modules" ] && [ ! -L "/app/sentry/node_modules" ]; then'; \
        echo '    BACKUP="node_modules_$(date +%Y%m%d%H%M%S)"'; \
        echo '    mv /app/sentry/node_modules /app/sentry/$BACKUP'; \
        echo 'fi'; \
        echo; \
        echo 'ln -s /app/sentry_deps/node_modules /app/sentry/node_modules'; \
        echo 'echo "✅ Build completed: ${SENTRY_VERSION}"'; \
        echo 'exec "$@"'; \
    } | tee /usr/local/bin/entrypoint.sh && chmod +x /usr/local/bin/entrypoint.sh

# Create directories in advance
RUN mkdir -p /app/sentry /app/sentry_deps/node_modules

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["sleep","infinity"]

V. Summary

  1. For legacy Docker versions / universal compatibility: prioritize RUN { ... } | tee.
  2. For short configurations: echo $'...' is the simplest option.
  3. Never use the #syntax=docker/dockerfile:1 heredoc syntax blindly—it causes severe incompatibility issues.
  4. All methods in this article are locally tested and validated with no unexplained errors, making them suitable for production, CI/CD, and Alpine Linux environments.

#Docker #DevOps #EnterprisePractice

Image NewsLetter
Icon primary
Newsletter

Subscribe our newsletter

Please enter your email address below and click the subscribe button. By doing so, you agree to our Terms and Conditions.

Your experience on this site will be improved by allowing cookies Cookie Policy