.NET 언어별 가이드
.NET 언어별 가이드
Docker를 사용해 .NET 어플리케이션을 컨테이너화하는 방법을 배워볼게요.
출처: 문서
본문
.NET 시작하기 가이드는 Docker를 사용해 컨테이너화된 .NET 어플리케이션을 만드는 방법을 알려줘요. 이 가이드에서 배울 내용:
- .NET 어플리케이션 컨테이너화 및 실행하기
- 컨테이너를 사용해 .NET 어플리케이션을 개발할 로컬 환경 설정하기
- 컨테이너를 사용해 .NET 어플리케이션 테스트 실행하기
.NET 시작하기 모듈을 완료하면, 이 가이드에 제공된 예제와 지침에 따라 나만의 .NET 어플리케이션을 컨테이너화할 수 있어야 해요.
.NET 어플리케이션 컨테이너화하기
사전 요구사항
- 최신 버전의 Docker Desktop 을 설치했어야 해요.
- git 클라이언트 가 있어야 해요. 이 섹션의 예제는 명령줄 기반 git 클라이언트를 사용하지만, 어떤 클라이언트든 사용할 수 있어요.
개요
이 섹션은 .NET 어플리케이션을 컨테이너화하고 실행하는 과정을 안내해요.
샘플 어플리케이션 가져오기
이 가이드에서는 미리 빌드된 .NET 어플리케이션을 사용할 거예요. 이 어플리케이션은 Docker Blog 기사인 Docker Desktop으로 멀티 컨테이너 .NET 앱 빌드하기 에서 빌드한 어플리케이션과 비슷해요.
터미널을 열고 작업할 디렉터리로 이동한 뒤, 다음 명령을 실행해 리포지토리를 클론해주세요.
$ git clone https://github.com/docker/docker-dotnet-sample
Docker 자산 만들기
이제 어플리케이션이 있으니 컨테이너화하는 데 필요한 Docker 자산을 만들 수 있어요. 공식 .NET 이미지나 Docker Hardened Images(DHI) 중에서 선택할 수 있어요.
팁: Gordon 은 내 어플리케이션에 맞춘 .dockerignore 를 제안해줘요.
Docker Hardened Images(DHI) 는 Docker가 유지 관리하는 최소화되고 안전하며 프로덕션 준비가 된 컨테이너 베이스·어플리케이션 이미지예요. DHI 이미지는 보안 개선을 위해 권장돼요. 취약점을 줄이고 규정 준수를 단순화하도록 설계됐어요.
Docker Hardened Images 사용
.NET용 Docker Hardened Images(DHI)는 Docker Hardened Images 카탈로그 에서 사용할 수 있어요. Docker Hardened Images는 구독 없이도 누구나 무료로 사용할 수 있어요. DHI 레지스트리에 로그인한 후 다른 Docker 이미지처럼 내려받아 사용할 수 있어요. 자세한 내용은 DHI 퀵스타트 가이드 를 참고하세요.
DHI 레지스트리에 로그인해주세요:
$ docker login dhi.io
.NET SDK DHI를 내려받아주세요(사용 가능한 버전은 카탈로그 확인):
$ docker pull dhi.io/dotnet:10-sdk
ASP.NET Core 런타임 DHI를 내려받아주세요(사용 가능한 버전은 카탈로그 확인):
$ docker pull dhi.io/aspnetcore:10
docker-dotnet-sample 디렉터리에 다음 파일들을 만들어주세요.
Dockerfile:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
FROM dhi.io/aspnetcore:10 AS final
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "myWebApp.dll"]
참고: DHI 런타임 이미지는 이미 비루트 사용자( nonroot , UID 65532)로 실행되므로 Dockerfile에서 사용자를 만들거나 USER 를 지정할 필요가 없어요. 이는 공격 표면을 줄이고 구성을 단순화해요.
compose.yaml:
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Docker Compose reference guide at
# https://docs.docker.com/go/compose-spec-reference/
# Here the instructions define your application as a service called "server".
# This service is built from the Dockerfile in the current directory.
# You can add other services your application may depend on here, such as a
# database or a cache. For examples, see the Awesome Compose repository:
# https://github.com/docker/awesome-compose
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker compose up`.
# depends_on:
# db:
# condition: service_healthy
# db:
# image: postgres
# restart: always
# user: postgres
# secrets:
# - db-password
# volumes:
# - db-data:/var/lib/postgresql/data
# environment:
# - POSTGRES_DB=example
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
# expose:
# - 5432
# healthcheck:
# test: [ "CMD", "pg_isready" ]
# interval: 10s
# timeout: 5s
# retries: 5
# volumes:
# db-data:
# secrets:
# db-password:
# file: db/password.txt
.dockerignore:
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/go/build-context-dockerignore/
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
공식 .NET 10 이미지 사용
docker-dotnet-sample 디렉터리에 다음 파일들을 만들어주세요.
Dockerfile:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
WORKDIR /app
COPY --from=build /app .
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
ENTRYPOINT ["dotnet", "myWebApp.dll"]
compose.yaml:
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Docker Compose reference guide at
# https://docs.docker.com/go/compose-spec-reference/
# Here the instructions define your application as a service called "server".
# This service is built from the Dockerfile in the current directory.
# You can add other services your application may depend on here, such as a
# database or a cache. For examples, see the Awesome Compose repository:
# https://github.com/docker/awesome-compose
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker compose up`.
# depends_on:
# db:
# condition: service_healthy
# db:
# image: postgres
# restart: always
# user: postgres
# secrets:
# - db-password
# volumes:
# - db-data:/var/lib/postgresql/data
# environment:
# - POSTGRES_DB=example
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
# expose:
# - 5432
# healthcheck:
# test: [ "CMD", "pg_isready" ]
# interval: 10s
# timeout: 5s
# retries: 5
# volumes:
# db-data:
# secrets:
# db-password:
# file: db/password.txt
.dockerignore:
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/go/build-context-dockerignore/
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
이제 docker-dotnet-sample 디렉터리에 다음 내용이 있어야 해요.
├── docker-dotnet-sample/
│ ├── .git/
│ ├── src/
│ ├── .dockerignore
│ ├── compose.yaml
│ ├── Dockerfile
│ └── README.md
이 파일들에 대해 더 알려면 Dockerfile , .dockerignore , compose.yaml 을 참고하세요.
어플리케이션 실행하기
docker-dotnet-sample 디렉터리 안에서 터미널에 다음 명령을 실행해주세요.
$ docker compose up --build
브라우저를 열고 http://localhost:8080 에서 어플리케이션을 확인해주세요. 간단한 웹 어플리케이션이 보여야 해요.
터미널에서 ctrl + c 를 눌러 어플리케이션을 중지해주세요.
백그라운드에서 어플리케이션 실행
-d 옵션을 추가하면 터미널에서 분리된 상태로 어플리케이션을 실행할 수 있어요. docker-dotnet-sample 디렉터리 안에서 터미널에 다음 명령을 실행해주세요.
$ docker compose up --build -d
브라우저를 열고 http://localhost:8080 에서 어플리케이션을 확인해주세요. 간단한 웹 어플리케이션이 보여야 해요.
터미널에서 다음 명령으로 어플리케이션을 중지해주세요.
$ docker compose down
Compose 명령에 대한 자세한 내용은 Compose CLI 참조 를 참고하세요.
.NET 개발에 컨테이너 사용하기
사전 요구사항
.NET 어플리케이션 컨테이너화하기 를 완료하세요.
개요
이 섹션에서는 컨테이너화된 어플리케이션을 위한 개발 환경을 설정하는 방법을 배워요. 여기에는 다음이 포함돼요:
- 로컬 데이터베이스 추가 및 데이터 영속화
- 코드를 편집·저장할 때 Compose가 실행 중인 Compose 서비스를 자동으로 업데이트하도록 구성하기
- .NET Core SDK 도구와 의존성이 포함된 개발 컨테이너 만들기
어플리케이션 업데이트
이 섹션은 업데이트된 .NET 어플리케이션이 들어 있는 docker-dotnet-sample 리포지토리 의 다른 브랜치를 사용해요. 업데이트된 어플리케이션은 .NET 어플리케이션 컨테이너화하기 에서 클론한 리포지토리의 add-db 브랜치 에 있어요.
업데이트된 코드를 얻으려면 add-db 브랜치를 체크아웃해야 해요. .NET 어플리케이션 컨테이너화하기 에서 내가 만든 변경 사항은 이 섹션을 위해 스태시할 수 있어요. 터미널에서 docker-dotnet-sample 디렉터리에 다음 명령을 실행해주세요.
이전 변경 사항을 스태시해주세요.
$ git stash -u
업데이트된 어플리케이션이 있는 새 브랜치를 체크아웃해주세요.
$ git checkout add-db
add-db 브랜치에서는 .NET 어플리케이션만 업데이트됐어요. Docker 자산은 아직 업데이트되지 않았어요.
이제 docker-dotnet-sample 디렉터리에 다음이 있어야 해요.
├── docker-dotnet-sample/
│ ├── .git/
│ ├── src/
│ │ ├── Data/
│ │ ├── Models/
│ │ ├── Pages/
│ │ ├── Properties/
│ │ ├── wwwroot/
│ │ ├── appsettings.Development.json
│ │ ├── appsettings.json
│ │ ├── myWebApp.csproj
│ │ └── Program.cs
│ ├── tests/
│ │ ├── tests.csproj
│ │ ├── UnitTest1.cs
│ │ └── Usings.cs
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── Dockerfile
│ └── README.md
로컬 데이터베이스 추가 및 데이터 영속화
컨테이너로 데이터베이스 같은 로컬 서비스를 설정할 수 있어요. 이 섹션에서는 데이터가 영속화되도록 볼륨과 데이터베이스 서비스를 정의하도록 compose.yaml 파일을 업데이트해요.
IDE 또는 텍스트 편집기로 compose.yaml 파일을 열어주세요. PostgreSQL 데이터베이스와 볼륨에 대한 주석 처리된 지침이 이미 포함되어 있는 것을 알 수 있을 거예요.
IDE 또는 텍스트 편집기로 docker-dotnet-sample/src/appsettings.json 을 열어주세요. 모든 데이터베이스 정보가 있는 연결 문자열을 볼 수 있을 거예요. compose.yaml 은 이미 이 정보를 포함하지만 주석 처리되어 있어요.
compose.yaml 파일에서 데이터베이스 지침의 주석을 해제해주세요.
다음은 업데이트된 compose.yaml 파일이에요.
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
db:
image: postgres:18
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
참고: Compose 파일의 지침에 대해 더 알려면 Compose 파일 참조 를 참고하세요.
Compose로 어플리케이션을 실행하기 전에, 이 Compose 파일이 secrets 를 사용하고 데이터베이스의 패스워드를 담는 password.txt 파일을 지정한다는 점을 주목하세요. 이 파일은 소스 리포지토리에 포함되어 있지 않으므로 직접 만들어야 해요.
docker-dotnet-sample 디렉터리에 db 라는 새 디렉터리를 만들고 그 안에 password.txt 라는 파일을 만들어주세요. IDE 또는 텍스트 편집기에서 password.txt 를 열고 다음 패스워드를 추가해주세요. 패스워드는 파일에 추가 줄 없이 한 줄이어야 해요.
example
password.txt 파일을 저장하고 닫아주세요.
이제 docker-dotnet-sample 디렉터리에 다음이 있어야 해요.
├── docker-dotnet-sample/
│ ├── .git/
│ ├── db/
│ │ └── password.txt
│ ├── src/
│ ├── tests/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── Dockerfile
│ └── README.md
다음 명령을 실행해 어플리케이션을 시작해주세요.
$ docker compose up --build
브라우저를 열고 http://localhost:8080 에서 어플리케이션을 확인해주세요. Student name is 라는 텍스트가 있는 간단한 웹 어플리케이션이 보여야 해요.
데이터베이스가 비어 있으므로 어플리케이션은 이름을 표시하지 않아요. 이 어플리케이션의 경우 데이터베이스에 접근해 레코드를 추가해야 해요.
데이터베이스에 레코드 추가
샘플 어플리케이션의 경우 샘플 레코드를 만들려면 데이터베이스에 직접 접근해야 해요. docker exec 명령으로 데이터베이스 컨테이너 안에서 명령을 실행할 수 있어요. 그 명령을 실행하기 전에 데이터베이스 컨테이너의 ID를 얻어야 해요. 새 터미널 창을 열고 다음 명령으로 실행 중인 모든 컨테이너를 나열해주세요.
$ docker container ls
다음 같은 출력이 보여야 해요.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb36e310aa7e docker-dotnet-sample-server "dotnet myWebApp.dll" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-dotnet-sample-server-1
39fdcf0aff7b postgres:18 "docker-entrypoint.s…" About a minute ago Up About a minute (healthy) 5432/tcp docker-dotnet-sample-db-1
이전 예제에서 컨테이너 ID는 39fdcf0aff7b 예요. 다음 명령으로 컨테이너의 postgres 데이터베이스에 연결해주세요. 컨테이너 ID를 내 컨테이너 ID로 바꾸세요.
$ docker exec -it 39fdcf0aff7b psql -d example -U postgres
마지막으로 데이터베이스에 레코드를 삽입해주세요.
example=# INSERT INTO "Students" ("ID", "LastName", "FirstMidName", "EnrollmentDate") VALUES (DEFAULT, 'Whale', 'Moby', '2013-03-20');
다음 같은 출력이 보여야 해요.
INSERT 0 1
exit 를 실행해 데이터베이스 연결을 닫고 컨테이너 셸에서 나가주세요.
example=# exit
데이터가 데이터베이스에 영속되는지 확인
브라우저를 열고 http://localhost:8080 에서 어플리케이션을 확인해주세요. Student name is Moby Whale 라는 텍스트가 있는 간단한 웹 어플리케이션이 보여야 해요.
터미널에서 ctrl+c 를 눌러 어플리케이션을 중지해주세요.
터미널에서 docker compose rm 을 실행해 컨테이너를 제거한 다음 docker compose up 을 실행해 어플리케이션을 다시 실행해주세요.
$ docker compose rm
$ docker compose up --build
브라우저에서 http://localhost:8080 을 새로고침하고 컨테이너가 제거되고 다시 실행된 후에도 학생 이름이 영속됐는지 확인해주세요.
터미널에서 ctrl+c 를 눌러 어플리케이션을 중지해주세요.
서비스 자동 업데이트
Compose Watch를 사용하면 코드를 편집·저장할 때 실행 중인 Compose 서비스를 자동으로 업데이트할 수 있어요. Compose Watch에 대한 자세한 내용은 Compose Watch 사용하기 를 참고하세요.
IDE 또는 텍스트 편집기에서 compose.yaml 파일을 열고 Compose Watch 지침을 추가해주세요. 다음은 업데이트된 compose.yaml 파일이에요.
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: rebuild
path: .
db:
image: postgres:18
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
Compose Watch로 어플리케이션을 실행하려면 다음 명령을 실행해주세요.
$ docker compose watch
브라우저를 열고 http://localhost:8080 에서 어플리케이션이 실행 중인지 확인해주세요.
이제 내 로컬 머신의 어플리케이션 소스 파일 변경 사항이 즉시 실행 중인 컨테이너에 반영될 거예요.
IDE 또는 텍스트 편집기에서 docker-dotnet-sample/src/Pages/Index.cshtml 을 열고 13행의 학생 이름 텍스트를 Student name is 에서 Student name: 으로 업데이트해주세요.
- <p>Student name is @Model.StudentName</p>
+ <p>Student name: @Model.StudentName</p>
Index.cshtml 에 변경 사항을 저장한 다음 어플리케이션이 재빌드될 때까지 몇 초 기다리세요. 브라우저에서 http://localhost:8080 을 새로고침하고 업데이트된 텍스트가 나타나는지 확인해주세요.
터미널에서 ctrl+c 를 눌러 어플리케이션을 중지해주세요.
개발 컨테이너 만들기
이 시점에서 컨테이너화된 어플리케이션을 실행하면 .NET 런타임 이미지를 사용하고 있어요. 이 작은 이미지는 프로덕션에는 좋지만 개발에 필요한 SDK 도구와 의존성이 없어요. 또한 개발 중에는 dotnet publish 를 실행할 필요가 없을 수 있어요. 멀티 스테이지 빌드를 사용해 같은 Dockerfile에서 개발과 프로덕션 모두를 위한 스테이지를 빌드할 수 있어요. 자세한 내용은 멀티스테이지 빌드 를 참고하세요.
Dockerfile에 새 개발 스테이지를 추가하고 compose.yaml 파일을 업데이트해 로컬 개발에 이 스테이지를 사용하세요.
다음은 업데이트된 Dockerfile이에요.
Docker Hardened Images 사용:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
FROM dhi.io/dotnet:10-sdk AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile
FROM dhi.io/aspnetcore:10 AS final
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "myWebApp.dll"]
공식 .NET 10 이미지 사용:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
WORKDIR /app
COPY --from=build /app .
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
ENTRYPOINT ["dotnet", "myWebApp.dll"]
다음은 업데이트된 compose.yaml 파일이에요.
services:
server:
build:
context: .
target: development
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: rebuild
path: .
environment:
- ASPNETCORE_ENVIRONMENT=Development
db:
image: postgres:18
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
이제 컨테이너화된 어플리케이션이 SDK 이미지(DHI면 dhi.io/dotnet:10-sdk , 공식 이미지면 mcr.microsoft.com/dotnet/sdk:10.0-alpine )를 사용하게 되며, 여기에는 dotnet test 같은 개발 도구가 포함돼요. 다음 섹션에서 dotnet test 를 실행하는 방법을 배워보세요.
컨테이너에서 .NET 테스트 실행하기
사전 요구사항
.NET 어플리케이션 컨테이너화하기 부터 시작해 이 가이드의 이전 모든 섹션을 완료하세요.
개요
테스팅은 현대 소프트웨어 개발의 필수적인 부분이에요. 테스팅은 개발 팀마다 많은 것을 의미할 수 있어요. 단위 테스트, 통합 테스트, 엔드투엔드 테스트가 있어요. 이 가이드에서는 개발할 때와 빌드할 때 Docker에서 단위 테스트를 실행하는 방법을 살펴볼 거예요.
로컬 개발 시 테스트 실행
샘플 어플리케이션에는 tests 디렉터리 안에 xUnit 테스트가 이미 있어요. 로컬에서 개발할 때 Compose를 사용해 테스트를 실행할 수 있어요.
docker-dotnet-sample 디렉터리에서 다음 명령을 실행해 컨테이너 안의 테스트를 실행해주세요.
$ docker compose run --build --rm server dotnet test /source/tests
다음이 포함된 출력이 보여야 해요.
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
명령에 대해 더 알려면 docker compose run 을 참고하세요.
빌드 시 테스트 실행
빌드할 때 테스트를 실행하려면 Dockerfile을 업데이트해야 해요. 테스트를 실행하는 새 테스트 스테이지를 만들거나, 기존 빌드 스테이지에서 테스트를 실행할 수 있어요. 이 가이드에서는 빌드 스테이지에서 테스트를 실행하도록 Dockerfile을 업데이트해요.
다음은 업데이트된 Dockerfile이에요.
Docker Hardened Images 사용:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
RUN dotnet test /source/tests
FROM dhi.io/dotnet:10-sdk AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile
FROM dhi.io/aspnetcore:10 AS final
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "myWebApp.dll"]
공식 .NET 10 이미지 사용:
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
RUN dotnet test /source/tests
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
WORKDIR /app
COPY --from=build /app .
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
ENTRYPOINT ["dotnet", "myWebApp.dll"]
다음 명령을 실행해 build 스테이지를 대상으로 이미지를 빌드하고 테스트 결과를 확인해주세요. 빌드 출력을 보려면 --progress=plain , 테스트가 항상 실행되게 하려면 --no-cache , build 스테이지를 대상으로 하려면 --target build 를 포함하세요.
$ docker build -t dotnet-docker-image-test --progress=plain --no-cache --target build .
다음이 포함된 출력이 보여야 해요.
#11 [build 5/5] RUN dotnet test /source/tests
#11 1.564 Determining projects to restore...
#11 3.421 Restored /source/src/myWebApp.csproj (in 1.02 sec).
#11 19.42 Restored /source/tests/tests.csproj (in 17.05 sec).
#11 27.91 myWebApp -> /source/src/bin/Debug/net10.0/myWebApp.dll
#11 28.47 tests -> /source/tests/bin/Debug/net10.0/tests.dll
#11 28.49 Test run for /source/tests/bin/Debug/net10.0/tests.dll (.NETCoreApp,Version=v10.0)
#11 28.67 Microsoft (R) Test Execution Command Line Tool Version 17.3.3 (x64)
#11 28.67 Copyright (c) Microsoft Corporation. All rights reserved.
#11 28.68
#11 28.97 Starting test execution, please wait...
#11 29.03 A total of 1 test files matched the specified pattern.
#11 32.07
#11 32.08 Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
#11 DONE 32.2s
요약
이 섹션에서 Compose로 로컬 개발 시 테스트를 실행하는 방법과 이미지를 빌드할 때 테스트를 실행하는 방법을 배웠어요.
관련 정보:
- Dockerfile 참조
- Compose 파일 참조
- Compose CLI 참조
더 알아보기 (Learn more)
- .NET
- Docker Hardened Images
- Docker Compose