WSL에서 Native Docker 실행하기

Microsoft loves Linux — 이미지 출처: https://arstechnica.com/gadgets/2018/03/microsofts-new-open-source-tool-lets-you-bring-your-own-linux-distro-to-windows/

NOTE: 공식적으로 WSL에서는 Native Docker를 실행할 수 없습니다. 이 아티클에서 설명하는 내용은 실험적인 기능에 관한 것으로, 실제 프로덕션 워크로드에 사용할 수 있는 내용이 아닙니다. 개발과 테스트 목적으로만 이 아티클의 내용을 활용하여 주십시오.

Windows 10 1803 버전부터는 WSL에서 그동안 지원되지 않았던 Unix 소켓과 백그라운드 데몬 지원이 정식으로 가능해졌습니다. 그 덕분에 Windows와 Linux 앱을 동시에 사용하는 것이 현실화되어가고 있습니다.

오늘 소개하려는 내용은 Native Docker 컨테이너에 관한 내용입니다. Docker Machine을 사용하거나, Docker for Windows가 아닌 정말 Native Docker를 WSL에서 실행하는 것에 관한 내용입니다. 이 방식의 경우 Hyper-V Isolation 기반이 아니기 때문에 가능한 범위에서 Linux 컨테이너를 CPU 가상화 Feature 없이 돌릴 수 있습니다. 그리고 이 때문에 Windows의 작업 관리자에서 docker 컨테이너 내부의 프로세스들을 볼 수 있습니다.

물론 WSL 그 자체는 온전한 리눅스 환경이 아니며, Docker의 실행에 필요한 모든 기능을 제공하지는 않습니다. 그리고 이 아티클에서 소개하지 못한 사용법으로 테스트를 하다보면 또 다른 문제가 나타날 수 있습니다. 필요한 상황에서만 적절하게 활용하시는 것을 권장합니다.

준비할 사항

이 아티클의 내용을 테스트해보려면 Windows 10 RS4 버전이 필요합니다. 이 아티클을 작성하는 2018년 4월 15일 현재, Release Preview Ring을 통하여 Windows 10 RS4 (17133.1) 버전을 받아보실 수 있습니다.

그리고 프로그램 추가/제거에서 Windows Subsystem for Linux를 아래 그림과 같이 설치하고 시스템을 다시 시작합니다.

Windows Subsystem for Linux 기능을 활성화하고 재부팅합니다.

다음으로 Ubuntu Linux를 Microsoft Store에서 App으로 다운로드받아 설치하도록 합니다.

Microsoft Store에서 Ubuntu 앱을 설치합니다.

Ubuntu Linux를 설치한 다음 실행하면 나타나는 기본적인 절차를 진행한 후에는 패키지 업데이트 (apt update && apt -y upgrade && apt -y autoremove)명령을 실행하여 최신 버전들로 패키지를 업그레이드합니다.

Docker 설치하기

모든 버전의 Docker가 WSL에서 실행을 지원하는 것은 아니며, 파일 시스템의 종류를 판정하는 동작이 들어간 최신 버전의 Docker에서는 컨테이너 생성을 위한 이미지 Pull을 수행할 때 실패하는 문제가 있습니다.

나중에 이 문제가 해결된 Docker 버전이 나올 수도 있지만,원활한 설명을 위하여 여기서는 17.03 버전으로 고정하여 설명하겠습니다.

Docker의 설치 과정 전반을 자동화해주는 스크립트를 이용하여 간단하게 설치를 진행해보겠습니다.

아래와 같이 명령어를 입력합니다.

curl https://releases.rancher.com/install-docker/17.03.sh | bash

설치 과정 중에 비밀 번호를 물으면, 비밀 번호를 입력하여 설치를 끝까지 진행합니다.

docker 명령을 sudo 없이 실행할 수 있도록 하기 위하여 아래 명령을 입력하여현재 로그인한 사용자가 docker 데몬에 액세스할 수 있도록 권한도 부여하도록 합니다. $USER는 whoami 명령으로 확인할 때 나오는 사용자 이름으로 대체합니다.

sudo usermod -aG docker $USER

패키지 매니저를 통한 업그레이드를 진행할 때 최신 버전으로 업그레이드가 되면 docker가 실행되지 않으므로 아래 명령어로 현재 버전의 docker를 유지하도록 고정합니다.

sudo apt-mark hold docker-ce

여기까지 설치를 완료하였습니다.

Native Docker 데몬 시작하고 사용하기

이제 설치가 끝났으니 실제로 Docker 데몬을 띄워보도록 하겠습니다. 계속하기 전에, WSL Ubuntu를 Windows에서 권한 상승 기능을 이용하여 새롭게 실행한 상태에서 아래 명령을 실행하도록 합니다. 이렇게 하지 않을 경우, Docker 데몬이 실행되지 않습니다.

sudo service docker start

참고: 이 과정을 Windows 측에서 자동으로 대행해주는 스크립트를 만들어서 공유했던 적이 있습니다. https://gist.github.com/rkttu/2d551d27aa70311c7963cbf2b26ae435 에서 스크립트를 내려 받은 다음, Windows 탐색기 등에서 “관리자 권한으로 실행” 기능으로 해당 스크립트를 실행하면 편리하게 Docker 데몬을 시작할 수 있습니다.

RS4 버전부터는 WSL Shell을 종료하더라도 Daemon 프로세스가 같이 종료되지 않기 때문에, 위의 명령을 실행한 다음에는 exit 명령을 입력하여 WSL Shell을 닫아도 됩니다.

이제부터는 일상적으로 사용하던 것과 마찬가지로 docker 명령을 다른 WSL Ubuntu의 Bash 셸에서 입력하고 사용할 수 있습니다. 이제 예를 들어 Mono 컨테이너 이미지를 받아서 간단한 C# 프로그램을 작성한다고 해보겠습니다.

docker pull mono:5.8
docker run -it --rm mono:5.8
cat > Program.cs
using System;
public static class Program {
 public static void Main(string[] args) {
 Console.Out.WriteLine(“Hello, World!”);
 }
}
<CTRL+Z>
mcs Program.cs
mono Program.exe

실행 결과는 다음과 같습니다.

Mono C# 컴파일러와 Mono 런타임을 리눅스 컨테이너로 WSL에서 실행했습니다.

네트워크 서버 테스트해보기

Docker로 리눅스 애플리케이션을 실행해볼 수 있다면 네트워크 기능도 사용할 수 있을지 궁금하실텐데요, 네트워크를 재정의하는 기능은 아쉽게도 동작하지 않습니다. 그러나 Port Expose 기능을 이용하여 Docker Daemon이 Windows를 통하여 연결을 받도록 할 수 있습니다.

실제에 가까운 애플리케이션을 구동해볼 수도 있지만 여기서는 nginx 컨테이너를 기준으로 빠르게 설명해보겠습니다.

docker pull nginx:latest
docker run -d --name=webtest -p 80:80 --rm nginx:latest

위의 명령을 실행한 후, http://localhost 로 웹 브라우저를 열어 접속하면 다음과 같이 표시되는 것을 볼 수 있습니다.

WSL 환경에서 nginx 컨테이너를 Hyper-V Isolation 없이 실행했습니다.

실제 네트워크 구성이 어떻게 되어있는지 살펴보는 것도 의미가 있을 것 같습니다. Windows 명령 프롬프트 창에서 아래와 같이 명령어를 입력하여, 현재 80 포트를 점유하고 있는 프로세스가 무엇인지 확인해보겠습니다.

netstat -ano

아래 그림 기준으로 15636번 프로세스가 80 포트를 수신 대기하고 있다고 나오는 것을 볼 수 있습니다.

80 포트를 15636번 프로세스가 수신 대기하고 있습니다.

그렇다면 15636번 프로세스가 무엇일까요? 바로 docker-proxy 프로세스입니다. 실제 리눅스 환경과 마찬가지로 docker-proxy 프로세스가 컨테이너와 바깥의 네트워크를 중계해주고 있는 것을 볼 수 있습니다.

docker-proxy 프로세스의 존재

그리고 당연히 nginx 프로세스도 실행 중인 것을 볼 수 있습니다.

nginx 프로세스

이와 같은 방법으로 WSL에서 리눅스 컨테이너를 직접 실행하고, 네트워크까지 지원되는 컨테이너를 만들 수 있습니다. 그리고 지금까지의 과정은 Hyper-V Isolation을 사용한 환경이 아니므로 중첩 가상화 기능을 제공하지 않는 VM 내에서도 사용해 볼 수 있는 방법이기도 합니다.

결론

Windows가 리눅스 컨테이너를 지원하게 하는 방법은 여러가지가 있습니다. 여기서 소개한 방법 이외에 공식적으로 거론되는 것은 LinuxKit을 이용한 LCOW (Linux Container on Windows) 방식이 더 대중적이며, LCOW는 Hyper-V Isolation을 이용하여 리눅스 컨테이너를 부팅하는 방식입니다. 이 방식은 현재 개발 중인 기능이고, Docker for Windows에서 Experimental Feature 옵션을 켜서 테스트해보실 수 있습니다.

그리고 WSL을 통하여 리눅스 컨테이너를 실행할 때는 WSL이 제공하는 리눅스의 기능 상의 한계를 그대로 컨테이너 내부에서도 답습하기 때문에, SQL Server의 리눅스 버전 컨테이너, VPN 연결상황에서 컨테이너 내부의 아웃바운드 연결 차단 문제, docker network create 명령 미지원 문제 등 여럿 완벽하지 못한 부분이 있습니다.

하지만 Docker for Windows나 Hyper-V 없이 간단히 컨테이너를 만들어 띄우거나, Docker 레지스트리로 리눅스 컨테이너 이미지를 빌드하고 Push 하는 기능을 이용할 수 있게 되므로, 적절히 활용하면 큰 도움이 될 것입니다.

Like what you read? Give 남정현 a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.