Docker 빌드 실패 해결: 3rd Party DLL 및 로컬 어셈블리 참조 가이드
닷넷(.NET) 프로젝트를 컨테이너화할 때 가장 흔히 마주치는 병목 현상 중 하나는 NuGet 패키지가 아닌 로컬 3rd Party DLL 참조 문제입니다. 로컬 환경에서는 정상 작동하던 빌드가 Docker 이미지 생성 과정에서만 실패하는 이유는 Docker의 '빌드 컨텍스트(Build Context)' 격리 특성 때문입니다. 본 가이드에서는 MSB3245 오류의 근본 원인을 분석하고, 멀티 스테이지 빌드를 활용한 표준 해결책을 제시합니다.
목차
1. 문제 상황: MSB3245 에러 분석
Docker 빌드 로그에서 다음과 같은 오류가 발생하며 프로세스가 중단된다면, 이는 컴파일러가 선언된 참조 파일을 찾지 못했음을 의미합니다.
error MSB3245: Could not resolve this reference. Could not locate the assembly "[LibraryName].dll".
Check to make sure the assembly exists on disk.
이 에러는 단순히 파일이 없는 것이 아니라, Docker 엔진이 접근할 수 있는 영역(Context)에 파일이 존재하지 않을 때 주로 발생합니다.
2. Docker 빌드 실패의 핵심 원인
- 빌드 컨텍스트(Build Context) 미포함:
docker build명령 시 지정한 경로 외부에 DLL이 있는 경우, Docker 데몬으로 전송되지 않아 참조가 불가능합니다. - 절대 경로 참조: 로컬 PC의 특정 경로(예:
C:\libs\..)로 설정된 DLL 참조는 리눅스 기반 컨테이너 환경에서 유효하지 않습니다. - .dockerignore 필터링:
bin이나obj폴더를 제외하는 설정 중에 실수로 필요한 DLL 파일까지 제외된 경우입니다. - 계층화된 복사 실패:
COPY명령 시 프로젝트 파일만 먼저 복사하고 DLL을 나중에 복사하면dotnet restore단계에서 참조 오류가 발생합니다.
3. 단계별 해결 방법
3.1 Dockerfile 복사 전략 수정
가장 중요한 포인트는 dotnet restore를 실행하기 전, 프로젝트 파일과 함께 모든 로컬 참조 DLL을 컨테이너 내부로 명시적 복사하는 것입니다.
WORKDIR /src
# 1. 프로젝트 파일 복사
COPY ["MyProject/MyProject.csproj", "MyProject/"]
# 2. 로컬 DLL 파일들을 프로젝트 구조와 동일하게 복사 (중요)
COPY ["MyProject/libs/ExternalLib.dll", "MyProject/libs/"]
# 3. 복구 및 빌드 수행
RUN dotnet restore "MyProject/MyProject.csproj"
COPY . .
WORKDIR "/src/MyProject"
RUN dotnet build -c Release -o /app/build
3.2 프로젝트 파일(.csproj) 상대 경로 확인
프로젝트 파일 내의 HintPath는 반드시 프로젝트 루트로부터의 상대 경로여야 하며, Docker 컨테이너 내부의 파일 구조와 일치해야 합니다.
libs\ExternalLib.dll
True
3.3 멀티 스테이지 빌드 활용 (Best Practice)
빌드 환경과 실행 환경을 분리하여 보안을 강화하고 이미지 크기를 최적화합니다.
# 빌드 스테이지
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
# 종속성 복사 및 캐싱
COPY ["MyProject.csproj", "./"]
COPY ["libs/", "./libs/"]
RUN dotnet restore "./MyProject.csproj"
# 소스 전체 복사 및 게시
COPY . .
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish
# 런타임 스테이지
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyProject.dll"]
4. 고도화를 위한 모범 사례
로컬 DLL 참조는 형상 관리와 버전 충돌의 위험이 큽니다. 장기적으로는 다음의 대안을 권장합니다.
- 사설 NuGet 서버 활용: DLL을 직접 관리하기보다 JFrog, ProGet 또는 GitHub Packages를 통해 버전 관리하십시오.
- 아티팩트 검증: Docker 이미지 빌드 후
docker run --rm your-image ls -R /app명령을 통해 DLL이 정상 배포되었는지 확인하십시오. - 보안 스캔: 3rd Party DLL은 보안 취약점의 통로가 될 수 있으므로 빌드 파이프라인에 Snyk 등의 스캔 도구를 통합하십시오.
결론
3rd Party DLL로 인한 Docker 빌드 실패는 결국 '파일 존재 여부'와 '참조 경로의 일관성' 문제입니다. Dockerfile 내에서 명시적인 COPY 명령을 통해 빌드 컨텍스트를 구성하고, 멀티 스테이지 빌드를 통해 런타임 환경까지 안전하게 아티팩트를 전달함으로써 문제를 해결할 수 있습니다. 위 전략을 통해 더욱 견고한 CI/CD 파이프라인을 구축하시기 바랍니다.