도커 데스크톱 없이 구축하는 WSL2와 도커 개발 환경

🧐 | 2022-09-23

안녕하세요, 넷마블 기술분석팀 박정욱입니다.

도커 데스크톱(Docker Desktop) 유료화 정책에 대해 대부분 알고 계시지만, 가끔 아직 모르시는 분들이 있으신 것 같습니다. 도커 데스크톱 유료화 정책 발표가 2021년 8월 31일에 있었으니, 어느덧 1년이 넘었네요. 당시에 발표한 유료화 정책을 적용하는 날은 2022년 2월 1일이었으니, 라이선스가 바뀐 지도 7개월이 넘었습니다.

도커 데스크톱에는 설치나 환경 설정 과정 등에서 얻을 수 있는 편의 사항이 은근 많이 있으므로, 도커 데스크톱 유료화 정책 시행에 맞춰서 무료 사용 요건을 확인하고 구매해서 사용하는 편이 가장 간편한 방법일 것입니다. 다만, 여러 사정으로 인해 그러지 못한 분들도 계시리라 생각합니다.

명시적으로 도커 데스크톱을 무료로 사용할 수 있는 범위

이 유료화 정책에서 재미난 포인트는 도커 데스크톱이라는 프로그램과 도커 엔진(Docker Engine)이 서로 별개 패키지라는 부분입니다. 커맨드라인으로 도커를 사용했던 분들께는 도커 엔진만으로도 충분하기 때문이죠.

도커 데스크톱의 가치

“도커 엔진으로 다 대처할 수 있다면, 도커 데스크톱은 왜 필요한가?”라는 질문을 하시는 분들도 계셔서, 아래 링크를 찾아왔습니다.

도커 데스크톱은 단순히 설치와 환경 설정 편의만을 위한 프로그램이 아닙니다. 개발과 운영을 위해 필요한 많은 요소를 품고 있습니다. 도커 데스크톱 공식 문서에 따르면, 도커 데스크톱 안에는 도커 엔진(Docker Engine), 도커 CLI 클라이언트(Docker CLI Client), 도커 빌드x(Docker Buildx), 도커 컴포즈(Docker Compose), 도커 콘텐트 트러스트(Docker Content Trust), 쿠버네티스(Kubernetes), 도커 자격 증명 도우미(Credential Helper) 등이 함께 들어있습니다. 그래서 단순히 도커 엔진을 넘어, 도커 생태계를 지탱하기 위한 대부분을 한번에 설치해서 쓸 수 있습니다.

그럼에도 불구하고, 이런저런 사정이 엮여 도커 데스크톱을 쓰긴 힘들고 도커 엔진이면 충분하신 분들이 계시리라 생각합니다. 그분들께 WSL2와 도커 엔진을 엮어 네이티브 도커처럼 쓰는 방법을 공유합니다.

WSL2와 도커 엔진

윈도우에 도커 데스크톱을 설치하지 않고 도커를 쓰기 위해서는 WSL2를 활용하면 됩니다. 앞서 살펴본 도커 데스크톱 구성요소 중, WSL2에는 도커 엔진을 설치하고 윈도우에는 도커 CLI 클라이언트를 설치해 이 둘을 연결하는 것이 핵심입니다. 설치하고 연결하는 것 자체는 단순합니다. WSL2 설치나 설정 관련해서는 아래 링크를 참고해주세요.

WSL2 설치와 세팅을 마쳤다면, 이제 도커 엔진을 설치할 차례입니다.

WSL2에 도커 엔진 설치

아래 가이드는 WSL 커널 버전 5.10을 기준으로 작성했습니다. WSL 커널 버전이 5.15 이상일 때는 새로 작성한 글을 참고하셔도 됩니다. 이 글과 새 글은 systemd를 지원하는 WSL 커널 버전 5.15의 특징을 살린 환경 설정 몇가지를 제외하면, 기본 맥락이 거의 동일합니다.

잠깐 20초만 한눈을 팔면, 멈춰 서는 WSL

WSL2에 특정 버전 도커를 지정해서 설치해야 하는 특별한 목적이 있지 않다면, 도커가 공식으로 제공하는 설치 스크립트를 이용하는 것이 좋습니다.

$ curl -sSL get.docker.com | sh

# Executing docker install script, commit: 4f282167c425347a931ccfd95cc91fab041d414f

WSL DETECTED: We recommend using Docker Desktop for Windows.
Please get Docker Desktop from https://www.docker.com/products/docker-desktop

You may press Ctrl+C now to abort this script.
+ sleep 20

도커 설치 스크립트를 실행 후에 WSL 환경에서는 도커 데스크톱을 쓰기를 추천한다는 문구(WSL DETECTED: We recommend using Docker Desktop for Windows.)가 나옵니다. 특별히 다른 반응을 하지 않고 20초만 기다리면, 도커 설치를 시작합니다.

도커가 잘 설치됐는지 확인해보겠습니다.

$ docker --version

Docker version 20.10.18, build b40c2f6

편의를 위한 sudo 권한 설정

‘docker’ 명령어 실행시 매번 ‘sudo’를 입력하지 않으려면, ‘sudoer’에서 ‘sudo’ 권한 유저 유무를 확인해야 합니다.

먼저 ‘sudo’ 그룹에 사용자가 들어가 있는지 확인해보겠습니다.

$ grep -E ‘sudo|wheel’ /etc/group

sudo:x:27:iamgroot

만약 ‘sudo:x:27:[username]’과 비슷한 메시지가 출력되지 않는다면, ‘sudoer’ 그룹에 사용자를 추가해야 합니다.

$ sudo usermod -aG sudo $USER

다음으로, ‘sudo’ 명령어를 쓸 수 있는 조건에 그룹이 들어가 있는지 확인해야 합니다.

$ sudo grep -E '%sudo|%wheel' /etc/sudoers

%sudo	ALL=(ALL:ALL)	ALL

예시처럼 ‘%sudo ALL=(ALL:ALL) ALL’과 비슷한 메시지가 나오는지 확인 후, 사용자를 ‘docker’ 그룹에 추가합니다.

$ sudo usermod -aG docker $USER

도커 컨텍스트 설정

도커 데스크톱이 자동으로 잡아주는 설정 중에는 도커 컨텍스트(Docker Context)도 있습니다. 도커 컨텍스트에는 도커 빌드나 배포 등 사용 과정에서 필요한 정보를 품고 있기 때문에, 환경 변수 설정을 해야 정상 동작 합니다.

‘.profile’이나 ‘.bashrc’에 도커 컨텍스트 환경 변수를 미리 넣어두면, WSL 콘솔에 로그인할 때 자동으로 환경 변수를 적용받습니다. 아래는 ‘.profile’ 파일에 도커 컨텍스트 환경 변수를 추가하는 예시입니다.

$ echo '' >> ~/.profile
$ echo '# set DOCKER_HOST for docker default context' >> ~/.profile
$ echo 'wsl_ip=$(ip addr show eth0 | grep -oP "(?<=inet\s)\d+(\.\d+){3}")' >> ~/.profile
$ echo 'export DOCKER_HOST=tcp://$wsl_ip:2375' >> ~/.profile

추가한 ‘.profile’ 환경 변수를 적용받으려면, WSL을 재실행해야 합니다.

WSL 재실행 전에는 도커 데몬 소켓 에러가 나지만, WSL 재실행 후에는 도커 데몬 소켓 에러 없이 바로 실행됩니다.

우분투 22.04 이상일 땐

만약 우분투 버전이 22.04 이상이라면, ‘iptables’ 설정을 먼저 변경하고 나서 이후 과정을 따라가야 합니다. 우분투 22.04 버전부터 ‘iptables-nft’가 기본 설정으로 잡혀있어서, WSL에서 도커를 사용할 때 호환성 이슈가 발생합니다. ‘iptables-nft’ 대신 ‘iptables-legacy’를 사용해야 도커 데몬을 실행할 수 있습니다.

우분투 20.04 이하 버전을 WSL에서 사용하시는 분들은 확인만 하고 그냥 넘어가셔도 됩니다.

$ sudo update-alternatives --config iptables

There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).

  Selection    Path                       Priority   Status
------------------------------------------------------------
* 0            /usr/sbin/iptables-nft      20        auto mode
  1            /usr/sbin/iptables-legacy   10        manual mode
  2            /usr/sbin/iptables-nft      20        manual mode

Press <enter> to keep the current choice[*], or type selection number: 1

update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode

‘iptables’ 설정 화면에서 ‘1’을 입력해 ‘iptables-legacy’를 선택하고, WSL을 재부팅 합니다. (WSL 재실행이 아닌, wsl --shutdown으로 실행하는 재부팅입니다.)

도커 데몬 실행

이제 도커 엔진 설치를 마쳤으니, 도커 데몬을 실행하겠습니다.

WSL 환경이라는 특징에 따라, WSL 내부로 직접 들어가지 않아도 윈도우에서 직접 WSL 내부 명령어를 실행할 수 있습니다. 도커 데몬(Docker Daemon, dockerd)은 백그라운드에서 도는 서비스이므로, 윈도우에서 직접 WSL 내부에 데몬을 띄울 간단한 배치 파일을 활용하면 편의성을 높일 수 있습니다.

아래는 WSL IP를 도커 데몬과 연결하는 예시 배치 스크립트입니다. 윈도우 메모장 등 편한 편집기에서 간단히 ‘start-dockerd-in-wsl.bat’ 등 편한 이름으로 저장하고 실행하면 됩니다. 배치 파일 자체는 dockerd를 백그라운로 실행하고 바로 종료됩니다. (배치 파일은 관리자 권한으로 실행해야 합니다.)

@echo Starting dockerd in WSL ...
@echo off
for /f "tokens=1" %%a in ('wsl sh -c "hostname -I"') do set wsl_ip=%%a
netsh interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%wsl_ip%
wsl -d Ubuntu -u root -e nohup sh -c "dockerd -H tcp://%wsl_ip% &" < nul > nul 2>&1

WSL 커널 버전이 5.15 이상이라면

이 글을 최초에 쓰던 시점에는 WSL 커널 버전이 5.10이었습니다. 시간이 많이 흐른 지금은 윈도우 업데이트에 맞물려 WSL 커널 버전이 5.15 이상인 분들이 늘어나면서, 기존 배치 파일에서 동작하지 않는 옵션이 생겼습니다. 만약 WSL 커널 버전이 5.15 이상이라면, 배치 파일을 아래처럼 바꿔서 쓰시면 됩니다.

@echo Starting dockerd in WSL ...
@echo off
if exist nohup.out del /f /q nohup.out
for /f "tokens=1" %%a in ('wsl sh -c "hostname -I"') do set wsl_ip=%%a
netsh interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%wsl_ip%

wsl -d Ubuntu -u root -e sudo systemctl stop docker.socket
wsl -d Ubuntu -u root -e sudo systemctl stop docker.service
wsl -d Ubuntu -u root -e nohup sh -c "dockerd -H tcp://%wsl_ip% &"

배치 파일 실행

배치 파일은 실행하고 바로 종료되지만, dockerd가 프로세스로 돌기 위한 웜업 시간이 다소 필요하므로 10~30초가량 대기후에 WSL 안으로 들어가서 확인하면 도커 데몬 정상 동작을 확인할 수 있습니다.

  • 도커 데몬 실행 배치 파일을 윈도우 시작 프로그램에 등록하거나 작업 스케줄러로 등록해두면, 윈도우 부팅에 맞춰 자동으로 도커 데몬이 실행될 수 있게 설정할 수 있습니다.
  • 윈도우11에서는 WSL 속 ‘/etc/wsl.conf’ 파일의 ‘[boot] command’를 사용하면 윈도우 부팅에 맞춰 자동으로 도커 데몬을 실행할 수 있습니다.

WSL에서 ‘.profile’이나 ‘.bash’에 자동 실행 코드를 추가해서 WSL 콘솔로 셸 로그인 시에 도커 데몬을 자동으로 실행하는 방법도 있습니다. 아래는 ‘.profile’에 도커 데몬 자동 실행을 설정하는 예시 설정입니다. 아래 설정 내용도 WSL 커널 버전 영향을 받으므로 꼭 참고해서 트러블슈팅하시길 바랍니다.

$ echo '' >> ~/.profile
$ echo '# start docker daemon automatically when logging in wsl shell' >> ~/.profile
$ echo 'if [ -z "$(ps aux | grep dockerd | grep -v grep)" ] ; then' >> ~/.profile
$ echo '    wsl_ip=$(ip addr show eth0 | grep -oP "(?<=inet\s)\d+(\.\d+){3}")' >> ~/.profile
$ echo '    netsh.exe interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=$wsl_ip' >> ~/.profile
$ echo '    wsl.exe -d Ubuntu -u root -e dockerd -H tcp://$wsl_ip >/dev/null 2>&1 & disown' >> ~/.profile
$ echo 'fi' >> ~/.profile

윈도우와 도커 클라이언트

도커 클라이언트 다운로드

도커 클라이언트(Docker Client)를 사용하면 도커를 사용할 때 윈도우에서 WSL에 설치한 도커 엔진을 바로 불러서 사용할 수 있습니다. 이때 WSL에 설치한 도커 엔진 버전에 맞는 클라이언트를 사용해야 하므로, 버전에 유의하셔야 합니다.

시스템 환경 변수 설정

도커 클라이언트만 사용할 경우, 압축 해제한 파일 중 ‘docker.exe’ 파일만 남기고 나머지는 삭제해도 됩니다. 그리고 ‘docker.exe’ 파일이 있는 경로를 ‘PATH’ 환경 변수에 추가하면, 윈도우 전역에서 도커를 바로 실행할 수 있습니다. 아래 이미지에서는 ‘C:\docker\bin’ 디렉터리에 도커 클라이언트 파일을 넣어둔 예시 상황입니다.

새로 추가한 시스템 환경 변수를 적용하려면 윈도우를 재부팅 해야 합니다. (뒤 과정에서 추가해야하는 시스템 환경 변수가 더 있으므로, 그까지 마친 후에 재부팅 하시길 추천합니다.) PATH 환경 변수 정상 반영 여부는 윈도우 터미널에서 도커 클라이언트 파일이 있지 않은 디렉터리에서 도커 클라이언트를 실행하면 확인할 수 있습니다.

$ C:\Users\iamgroot> docker --version

Docker version 20.10.18, build b40c2f6

도커 클라이언트와 도커 데몬 연결

윈도우에 있는 도커 클라이언트와 WSL 안에 있는 도커 데몬을 연결하면, 윈도우에서 도커 엔진을 곧바로 쓸 수 있습니다. 이 둘 사이를 연결하려면, 도커 호스트 정보를 윈도우 시스템 환 변수에 추가해서 등록하면 됩니다.

새 시스템 변수 추가 화면에서 변수 이름은 ‘DOCKER_HOST’, 변수 값은 ‘tcp://localhost:2375’라고 입력합니다.

// 도커 컨텍스트 환경 변수
DOCKER_HOST=tcp://localhost:2375

이제 시스템 환경 변수를 적용하기 위해 윈도우를 재부팅하고, 도커 클라이언트와 도커 데몬이 정상적으로 연결됐는지 윈도우 터미널에서 도커를 실행해 확인합니다.

$ C:\Users\iamgroot> docker ps

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

$ C:\Users\iamgroot> docker run hello-world

이제 모든 설정이 끝났습니다.

환경 변수 적용을 위한 재부팅이 귀찮다면

시스템 환경 변수 설정값은 윈도우 부팅 과정에서 ‘explorer.exe’ 파일을 프로세스로 실행하면서 얻는 정보입니다. 이 시점에 얻은 정보를 후에 실행하는 프로그램들이 상속받아 사용하죠. 만약 이 순서과 과정을 이해하고 계신다면, 꼭 윈도우를 재부팅 하지 않아도 ‘explorer.exe’ 파일 프로세스를 제어하는 것만으로도 시스템 환경 변수를 변경할 수 있습니다.

기존에 실행 중인 윈도우 터미널이 있다면, 시스템 환경 변수도 업데이트 이전 정보를 받아왔으므로 종료합니다. 그리고 프로세스로 떠 있는 ‘explorer.exe’를 강제 종료하고 재실행하면, 변경한 시스템 환경 변수를 바로 적용받을 수 있습니다.

$ C:\Users\iamgroot> taskkill /f /im explorer.exe

$ C:\Users\iamgroot> explorer.exe

WSL2로 도커 데스크톱 없이 쓰는 도커

결국 도커 데스크톱을 쓸 땐 몇 번 클릭만으로 끝나는 설정과 패키지를 여러 수작업으로 완성한 기분이 들기도 합니다. 그래도 WSL이 WSL1에서 WSL2로 업그레이드된 덕분에 이런 대안을 사용할 수 있어서 다행이기도 합니다. 평소 비주얼 스튜디오 코드 등에서 사용하던 기본 도커 확장팩과도 완벽히 연동된다는 점도 덤입니다.

분명히 도커 데스크톱은 존재의 가치가 충분합니다. 다만 각자가 처한 환경과 여건이 다른 만큼, 여러 사정으로 인해 도커 데스크톱을 쓰지 못하고 계신 분들께 도움이 되기를 바랍니다.