본문 바로가기
카테고리 없음

Docker 빌드 시 CRLF(Line Ending) 문제 자동 해결하기

by 샘오리 2026. 7. 27.
728x90

개요

Windows 환경에서 작성한 설정 파일이나 쉘 스크립트를 Linux 기반 Docker 이미지에 포함시키다 보면 예상치 못한 오류가 발생하는 경우가 있다.

특히 Nginx 설정 파일, Logrotate 설정 파일, Shell Script 등을 Windows에서 수정한 뒤 그대로 이미지에 포함하면 컨테이너 실행 시 오류가 발생하거나 설정 파일을 정상적으로 읽지 못하는 현상이 발생할 수 있다.

이번 글에서는 Docker 빌드 과정에서 CRLF(Line Ending)를 자동으로 LF 형식으로 변환하도록 수정한 사례를 정리해본다.


증상

가장 흔하게 발생하는 증상은 다음과 같다.

/bin/sh^M: bad interpreter: No such file or directory

또는

/usr/bin/env: 'bash\r': No such file or directory

쉘 스크립트가 정상적으로 존재함에도 실행되지 않는다.

경우에 따라서는 Nginx 설정 파일이나 Cron 설정 파일이 정상적으로 읽히지 않는 현상도 발생할 수 있다.


원인

원인은 Windows와 Linux의 줄바꿈(Line Ending) 방식 차이에 있다.

운영체제별 기본 줄바꿈 문자는 다음과 같다.

운영체제줄바꿈

Windows CRLF (\r\n)
Linux / Unix LF (\n)

 

Windows에서 저장된 파일에는 줄 끝마다 \r 문자가 포함된다.

Linux는 이 문자를 줄바꿈 문자로 인식하지 않기 때문에 파일 내부에 불필요한 제어 문자가 남게 된다.


확인 방법

CRLF 형식으로 저장된 파일은 vi 또는 cat 명령으로 확인할 수 있다.

예를 들어 다음과 같이 표시된다.

server {
    listen 80;^M
    server_name localhost;^M
}^M

또는

#!/bin/sh^M
echo "start"^M

여기서 보이는 ^M 이 바로 CR(Carriage Return, \r) 문자다.

정상적인 Linux 파일이라면 다음과 같이 보여야 한다.

#!/bin/sh
echo "start"

또는 다음 명령으로도 쉽게 확인할 수 있다.

cat -A run.sh

결과:

#!/bin/sh^M$
echo "start"^M$

^M 이 보인다면 해당 파일은 CRLF 형식으로 저장된 상태다.


해결 방법 1. 수동으로 변환하기

가장 간단한 방법은 sed를 이용해 CR 문자를 제거하는 것이다.

단일 파일이라면 다음과 같이 처리할 수 있다.

sed -i 's/\r$//' run.sh
 

변환 전:

#!/bin/sh^M
echo "start"^M
 

변환 후:

#!/bin/sh
echo "start"
 

해결 방법 2. 디렉터리 전체 변환하기

설정 파일이 여러 개라면 find와 함께 사용할 수 있다.

find . -type f -exec sed -i 's/\r$//' {} +
 

현재 디렉터리 이하의 모든 파일에 대해 CR 문자를 제거한다.

다만 바이너리 파일까지 포함될 수 있으므로 실제 환경에서는 대상 디렉터리를 제한하는 것이 좋다.

예시:

find /etc/nginx -type f -exec sed -i 's/\r$//' {} +

해결 방법 3. Docker 빌드 과정에서 자동화하기 (추천)

개발자가 Windows를 사용하든 Linux를 사용하든 동일한 결과를 보장하려면 Docker 빌드 단계에서 변환하는 것이 가장 확실하다.

예를 들어 실행 스크립트만 처리하려면:

RUN sed -i 's/\r$//' /app/run.sh
 

Nginx 설정 파일 전체를 처리하려면:

RUN find /etc/nginx -type f -exec sed -i 's/\r$//' {} +
 

Cron 설정 파일도 포함하려면:

RUN find /etc/crontabs -type f -exec sed -i 's/\r$//' {} +
 

왜 빌드 단계에서 처리하는가

개발자 PC 설정에 의존하면 다음과 같은 문제가 발생할 수 있다.

  • Windows에서 수정
  • CRLF로 저장
  • Git Push
  • Docker Build
  • 운영 환경 장애 발생

반면 빌드 단계에서 강제로 정규화하면

개발 환경
    ↓
Docker Build
    ↓
CRLF 제거
    ↓
이미지 생성
    ↓
운영 환경 배포

어떤 환경에서 파일을 수정했는지와 관계없이 동일한 결과를 보장할 수 있다.


적용 효과

해당 구문 적용 후 다음과 같은 효과를 얻을 수 있었다.

  • Shell Script 실행 오류 방지
  • Nginx 설정 파일 파싱 문제 예방
  • Cron 설정 파일 오류 예방
  • Logrotate 설정 파일 오류 예방
  • 개발자 OS에 의존하지 않는 빌드 결과 보장

특히 운영 환경에서만 간헐적으로 발생하는 "왜 이 서버만 안되지?" 유형의 문제를 사전에 차단할 수 있다.


결론 

Line Ending 문제는 매우 단순하지만 생각보다 찾기 어려운 장애 원인이다.

파일을 열어보면 정상으로 보이고, Git에서도 차이가 보이지 않으며, Windows에서는 문제없이 동작하는 경우가 많다.

하지만 Linux 입장에서는 줄 끝에 숨어 있는 \r 문자 하나 때문에 설정 파일 파싱 실패, 쉘 스크립트 실행 실패, Cron 작업 미등록 같은 문제로 이어질 수 있다.

특히 Docker 환경에서는 이미지 빌드 단계에서 CRLF를 제거하는 방어 코드를 추가해 두는 것이 가장 확실한 해결 방법 중 하나라고 볼 수 있다.

728x90