>> 이전 글 참조1: vs2017에서 ASP.NET Core Docker 컨테이너 배포 (1/2) >> 이전 글 참조2: vs2017에서 ASP.NET Core Docker 컨테이너 배포 (2/2) |
이번에는 최신 .NET Core SDK 3.1 환경에서 ASP.NET Core 앱을 docker-compose를 통해 배포해 봤다.
프로젝트는 이전에 썼던 tutorialapp를 똑같이 썼고(Visual Studio 2019에서 3.1 버전으로 생성 후 빌드),
MariaDB를 추가로 Docker에 올려서 동일한 브릿지 네트워크로 구성해서 바로 사용 가능한 환경으로 만들어 봤다.
[docker-compose.yml(1/2)]
version: '3.1'
volumes:
v_db: {}
networks:
v_network:
driver: bridge
services:
db:
container_name: mariadb
image: mariadb:latest
restart: always
ports:
- 3306:3306
volumes:
# mariadb data folder
- v_db:/var/lib/mysql
# mariadb config folder
- ./db/config:/etc/mysql/conf.d
networks:
- v_network
environment:
# mariadb root password (new)
MYSQL_ROOT_PASSWORD: qwer1234!
TZ: Asia/Seoul
...
- v_db라는 가상 볼륨을 생성해서 MariaDB 데이터 저장소로 사용했다.
이렇게 하면 동일한 저장소를 여러 Docker 환경에서 계속 재사용이 가능하다. - 기본 브릿지 네트워크 대신 v_network라는 이름으로 생성한 네트워크를 사용했다.
이런 방법으로 필요한 경우 external, internal로 네트워크를 나눌 수도 있다. - MariaDB의 기본 환경설정 파일인 /etc/mysql/conf.d/my.cnf 파일을 다운로드 받아서
로컬 호스트의 ./db/config/my.cnf 파일로 저장하고 그 파일이 사용되도록 했다.
[my.cnf]
# my.cnf
# MariaDB-specific config file.
# Read by /etc/mysql/my.cnf
[client]
# Default is Latin1, if you need UTF-8 set this (also in server section)
#default-character-set = utf8
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
#
# * Character sets
#
# Default is Latin1, if you need UTF-8 set all this (also in client section)
#
#character-set-server = utf8
#collation-server = utf8_general_ci
#character_set_server = utf8
#collation_server = utf8_general_ci
# Import all .cnf files from configuration directory
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
!includedir /etc/mysql/mariadb.conf.d/
lower_case_table_names = 1
- utf-8 인코딩 대신에 utf-8 mb4 인코딩을 사용했다. 최신 인터넷에서 유행하는 이모지(emoji)를 저장하고 표현하려면 mb4 인코딩을 써야 한다. 회사 업무용으로는 그닥 필요가 없겠지만.
- 마지막 lower_case_table_names는 테이블 대소문자 구분을 하지 않고 일괄 소문자로 표시할 것인가의 여부로, Windows용 MariaDB에는 기본적으로 설정되어 있는데(대소문자 구분하지 않음), Docker용이나 Linux 용 MariaDB에는 이 값이 설정되어 있지 않아 대소문자를 가린다. 혹시 모르니 설정해 준다.
가상 볼륨을 따로 저장해서 호스트로 복사한다거나 반대의 작업을 하려고 할 때는 아래와 같이 하면 된다.
docker-hub에 미리 만들어져 있는 hello-world라는 샘플 템플릿 이미지를 사용하면 작고 가벼운 임시 컨테이너 이미지를 만들 수 있다.
D:\tutorialapp\Docker> docker volume ls DRIVER VOLUME NAME local docker_v_db D:\tutorialapp\Docker> docker container create --name dummy -v docker_v_db:/root hello-world D:\tutorialapp\Docker> docker cp dummy:/root/. ./db/init_data/. D:\tutorialapp\Docker> docker rm dummy |
로컬 호스트로 복사한 다음 지워버리면 끝. 파일 복사 작업을 할 때 컨테이너를 시작할 필요는 없다.
또는 가상 볼륨이 없는 경우 아예 미리 별도로 만들어서 파일을 복사한 다음 연결해서 사용할 수도 있다.
D:\tutorialapp\Docker> docker volume ls D:\tutorialapp\Docker> docker volume create docker_v_db D:\tutorialapp\Docker> docker container create --name dummy -v docker_v_db:/root hello-world D:\tutorialapp\Docker> docker cp ./db/init_data/. dummy:/root/. D:\tutorialapp\Docker> docker rm dummy |
>> 참고: docker-compose.yml 내부에서 사용되는 볼륨이나 네트워크 이름 앞에는 기본적으로 현재 작업 중인 상위 폴더명이 붙게 된다. 위 예제와 같이 v_db 볼륨의 실제 이름은 docker_v_db가 되는 식.
여기까지가 MariaDB 관련 docker 컨테이너를 준비한 부분이고,
다음은 ASP.NET Core 앱 컨테이너.
[Dockerfile.compose]
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY publish/. ./
COPY appsettings.Docker.json ./appsettings.json
ENTRYPOINT ["dotnet", "PnP.TutorialWeb.Core.dll"]
- ASP.NET Core 3.1 이미지(bionic)를 기반으로 작업했다.
용량을 줄인 buster나 buster-slim 이미지를 쓰면 TLS 등이 정상 동작하지 않아 MSSQL 접속 등 안되는 게 많다.
System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 31) - ASP.NET Core 앱을 빌드하고 게시한 publish 폴더를 현재 경로로 복사한 다음 컨테이너 이미지 내 /app 경로에 복사해서 올렸다. 상위 폴더를 지정할 수 없으므로 이 작업은 ASP.NET Core 앱 변경 시 빌드-게시-복사 작업을 매번 다시 해야 한다.
- ASP.NET Core 설정파일인 appsettings.json 파일은 로컬 호스트에 따로 준비해 둔 파일로 복사/교체했다.
[docker-compose.yml(2/2)]
...
tutorialapp:
build:
context: .
dockerfile: ./Dockerfile.compose
ports:
- 5000:80
- 5001:443
volumes:
- ./logs/:/app/logs/
networks:
- v_network
- Dockerfile.compose로 /app 경로에 ASP.NET Core 컨테이너를 설치 후 빌드하고
- 혹시 몰라 로그 파일은 /app/logs에 기록하는데, 로컬 호스트에서 쉽게 확인 가능하도록 볼륨을 연결했다. 이렇게 하면 현재 경로 하위의 logs 폴더에 로그 파일이 생기고, 컨테이너가 삭제되더라도 해당 로그는 유지된다.
- 네트워크는 위 MariaDB에서 사용한 동일 네트워크, v_network를 함께 쓰도록 했다.
위와 같이 Dockerfile.compose 파일을 별도로 만들어서 매번 ASP.NET Core용 docker 컨테이너를 새로 빌드하거나 이미 빌드/게시된 결과물을 이용해서 컨테이너를 만들 수도 있지만, 개발/테스트 환경처럼 최종 운영서버에 배포하는 경우가 아닌 이상 매번 그런 작업을 하기에는 시간도 오래 걸리고 불편하다. 그래서 게시된 로컬 호스트 폴더를 그대로 volumes로 연결만 해서 바로 사용하는 방법으로 바꿔 봤다.
D:\tutorialapp> aspnet publish -c Release -o bin\Release\netcoreapp3.1\publish ㄴbin\Debug ㄴbin\Release ㄴbin\Release\netcoreapp3.1 ㄴbin\Release\netcoreapp3.1\publish D:\tutorialapp\Docker> mklink /j publish ..\bin\Release\netcoreapp3.1\publish D:\tutorialapp\Docker> dir pub* D 드라이브의 볼륨: DATA 볼륨 일련 번호: FEAA-4CE1 D:\tutorialapp\Docker 디렉터리 2020-04-22 오후 01:01 <JUNCTION> publish [D:\tutorialapp\bin\Release\netcoreapp3.1\publish] 0개 파일 0 바이트 1개 디렉터리 772,761,542,656 바이트 남음 |
Docker는 현재 폴더 상위의 다른 폴더를 이용할 수 없지만, 심볼릭 링크(symbolic link)나 디렉터리 교차점(junction) 기법을 사용하면 다른 경로에 있는 파일이나 폴더를 굳이 복사하지 않고도 쉽게 가져다 쓸 수 있다. 위 화면은 상위 폴더에 배포된 publish 폴더를 현재 경로로 복사해 오지 않고 디렉터리 교차점으로 연결한 것. 이렇게 하면 앱 변경 시 매번 게시된 폴더를 다시 복사해 올 필요가 없다, 자동으로 연결되니까. (단, Dockerfile 내에서는 로컬 경로에 심볼릭 링크나 디렉터리 교차점이 있으면 경로 인식이 제대로 되지 않으므로 사용하면 안된다. docker-compose에서만 사용 가능하다.)
이를 활용하면 Dockerfile 없이도 비교적 쉽게 ASP.NET Core 앱 컨테이너를 만들 수 있다.
[docker-compose.yml(2/2)]
...
tutorialapp:
container_name: tutorialapp
image: mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic
ports:
- 5000:80
- 5001:443
volumes:
- ./publish/:/app/
- ./appsettings.Docker.json:/app/appsettings.json
- ./logs/:/app/logs/
networks:
- v_network
working_dir: /app
entrypoint:
- dotnet
- TutorialWeb.Core.dll
- 기본 이미지를 mcr.microsoft.com 레지스트리 허브에 있는 이미지로 직접 지정했다.
- 로컬 게시 폴더(디렉터리 교차점)를 컨테이너 내부의 /app 경로와 연결했다. 이렇게 하면 매번 새로 컨테이너를 빌드하지 않고 로컬에서 앱 빌드 후 게시만 하면 컨테이너에 곧장 반영되므로 개발 환경일 때 매우 유용하다.
- ASP.NET Core 설정파일인 appsettings.json 파일은 로컬 호스트에 있는 파일을 사용하도록 했다. 역시 이렇게 하면 컨테이너에 들어가서 수정하거나 매번 복사해 줄 필요가 없다.
- 로그 폴더 역시 로컬 호스트로 연결된 곳에 생성되도록 했다.
- 현재 작업 경로 설정은 working_dir로 한다. Dockerfile의 WORKDIR과 동일한 개념. ASP.NET Core 앱은 작업 경로가 다르면 정상 실행이 되지 않는다. 꼭 필요한 설정.
- Dockerfile이 없으므로 entrypoint나 command는 당연히 따라 붙어야 한다.
위 두 개를 합친 전체 docker-compose.yml은 아래와 같다.
[docker-compose.yml]
version: '3.1'
volumes:
v_db: {}
networks:
v_network:
driver: bridge
services:
db:
container_name: mariadb
image: mariadb:latest
restart: always
ports:
- 3306:3306
volumes:
# mariadb data folder
- v_db:/var/lib/mysql
# mariadb config folder
- ./db/config:/etc/mysql/conf.d
networks:
- v_network
environment:
# mariadb root password (new)
MYSQL_ROOT_PASSWORD: qwer1234!
TZ: Asia/Seoul
tutorialapp:
container_name: tutorialapp
image: mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic
ports:
- 5000:80
- 5001:443
volumes:
- ./publish/:/app/
- ./appsettings.Docker.json:/app/appsettings.json
- ./logs/:/app/logs/
networks:
- v_network
working_dir: /app
entrypoint:
- dotnet
- TutorialWeb.Core.dll
끝.
'Tech: > Server·IIS' 카테고리의 다른 글
Exchange EdgeSync 인증서 교체 (0) | 2020.06.25 |
---|---|
Docker ASP.NET Core HTTPS로 동작하게 만들기 (0) | 2020.06.03 |
vs2017에서 ASP.NET Core Docker 컨테이너 배포 (2/2) (0) | 2020.04.10 |
vs2017에서 ASP.NET Core Docker 컨테이너 배포 (1/2) (0) | 2020.04.09 |
IIS 서버 로컬에서 Windows 인증이 안되는 이유 및 방법 (1) | 2019.11.15 |