😺

WSL2 + Docker + VS CodeでゼロからRの解析環境をつくる

2022/10/22に公開

1. はじめに

1.1. この記事の趣旨

この記事は、GNU R(以下、R)の解析環境を、Windows Subsystem for Linux (WSL) 2 + Docker + Visual Studio Code(VS Code)でセットアップする手順をまとめたものです。時間をかけずに再現・共有可能な統計解析環境を作りたいと思い、備忘録を兼ねて書きました。

1.2. 背景

私の専門は医療分野のメタアナリシスの応用で、解析にはRを使用しています。これまではWindows 10 + R + RStudio Desktopという環境で解析をしていたのですが、日本語版のWindows 10とRおよびRStudio Desktopの組み合わせには文字コードの相違に由来した不具合が複数あり、解決することが困難でした。

Windows 10にはWSLというWindows上でLinux環境を動かす仕組みがあり、バージョン2のアーキテクチャ(WSL2、May 2020 Updateで正式リリース)では従来あったLinuxとの互換性の問題が解決され、パフォーマンスも改善されました。そこで、Windows上でRを実行するのではなく、WSL2-Linux上でRを実行することで、文字化けして読めないエラーコードとおさらばすることにしました。

また、ここ最近は統計解析に関する論文を出版する際に、解析コードやデータセットを共有しようという潮流があり、私も自分の解析環境を簡単に共有・再現できたらいいなと思うようになりました。WSL2をバックエンドにするとDockerがすんなり動くようなので、RとRStudioはコンテナー上で動かすことにしました。WindowsとLinuxの両方で作業することになるので、WSL上のコンテナーはVS codeのリモート開発機能を利用して操作することにしました。

1.3. 実行環境

  • OS:Windows 10 Pro(バージョン:21H2、OSビルド19044.1586)

1.4. やりたいこと

Dockerと、Rの checkpoint パッケージで解析環境全体のバージョンを管理し、他のユーザー(研究者)が同じ環境を簡単に再現できるようにする。

  • VS Codeをインターフェイスとして、WSL2-Linux上でDockerを使用する。
  • Docker Compose V2でrocker/rstudioイメージからR + RStudio環境を立ち上げる。
  • WSL2-LinuxのGitでソースコード等をバージョン管理し、最終的にGitHub + 論文で公開する。

2. 解析環境の構築

2.1. 手順

以下の順番で進めます。

  1. WSL2を有効化し、Ubuntuをインストールして設定する
  2. Docker Desktop for Windowsをインストールして設定する
  3. VS Codeをインストールして設定する
  4. Gitをインストールして設定する
  5. Rプロジェクトを作成する
  6. VS codeからRStudio Serverを起動する

2.2. WSL2を有効化し、Ubuntuをインストールして設定する

2.2.1. 参照したドキュメント

2.2.2. WSL2の有効化

管理者権限のPowerShellで以下のコマンドを入力して実行し、PCを再起動します。

PowerShell
wsl --install

2.2.3. Ubuntuのインストールと設定

PCを再起動すると、Ubuntuのターミナルが開いてインストールが進行します。Ubuntuのインストール完了後に、Linuxのユーザー名とパスワードを設定します。そのまま、ターミナルでログインシェル:bashが起動していますので以下のコマンドを実行し、Ubuntuのパッケージ管理システム:Advanced Packaging Tool(APT)のライブラリを更新してからパッケージをアップグレードします。

bash
sudo apt update && sudo apt upgrade

Windows-Linux間でファイルのやり取りをしようとすると、ファイルシステムが異なるため処理に時間がかかります。そのため、原則として統計解析に使用するファイルはすべてLinuxファイルシステム内に配置します。Windowsファイルシステムから統計解析で使用するファイルにアクセスしたい場合は、以下のコマンドを実行し、カレントディレクトリをエクスプローラーで開きます。この時、Windows側から仮想的なホスト wsl$ を介したファイル共有という形で、Linuxファイルシステムにアクセスしています。

bash
explorer.exe .

LinuxディストリビューションとWSLのバージョンを確認しておきます。PowerShellで以下のコマンドを実行します。

PowerShell
wsl --list --verbose

【実行結果】

  NAME      STATE           VERSION
* Ubuntu    Running         2

Ubuntuがインストールされており、WSL2で稼働中であることが確認できます。これだけではUbuntuのバージョンがわかりませんが、この「無印Ubuntuアプリケーション」では、インストール時点で最新の長期サポート(LTS:Long Term Support)版が提供される仕様です。

bashで以下のコマンドを実行することでインストールされたUbuntuのバージョンを確認できます。

bash
lsb_release --all

【実行結果】

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.4 LTS
Release:        20.04
Codename:       focal

2022年3月時点で最新のUbuntu 20.04.4 LTSがインストールされていることがわかります。なお、すでにインストールされているUbuntuは自動でアップグレードされるわけではないため、必要に応じて以下のコマンドを実行し、自分でアップグレードする必要があります。Ubuntu 20.04 LTSのサポートは2025年4月までです。

bash
sudo do-release-upgrade

2.2.4. Windows Terminalの設定(オプション)

Windows Terminalを使用している場合は、以下のように設定します。

  • Ubuntuの開始ディレクトリを \\wsl$\Ubuntu\home\UseName に変更する

2.3. Docker Desktop for Windowsをインストールして設定する

2.3.1. 参照したドキュメント

2.3.2. Docker Desktop for Windowsのインストール

インストーラーを使ってDocker Desktop for Windowsをインストールします。今回はDocker Desktop 4.6.0をインストールしました。インストールが完了したら、スタートメニューからDocker Desktopを起動し、設定画面に移動し、以下のように設定を変更・確認します。

  • Setting > General
    • "Open Docker Dashboard at startup" のチェックを外します
    • "Use the WSL 2 based engine" がオンになっていることを確認します
  • Setting > Resources > WSL Integration
    • "Enable integration with my default WSL distro" がオンになっていることを確認します
    • "Enable integration with additional distros" で必要な他のディストリビューションでもWSL統合を有効にします(今回は該当なし)

以下のコマンドを実行し、DockerとDocker Composeのバージョンを表示することで、インストールされていることを確認します。

Bash
docker --version && docker-compose --version

【実行結果】

Docker version 20.10.13, build a224086
Docker Compose version v2.3.3

2.3.3. Hello world

単純なDockerイメージを呼び出して、機能をテストします。

bash
docker run hello-world

【実行結果(抜粋)】

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:4c5f3db4f8a54eb1e017c385f683a2de6e06f75be442dc32698c9bbe6c861edd
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

Hello ! 問題なさそうですね。

2.4. VS Codeをインストールして設定する

2.4.1. 参照したドキュメント

2.4.2. VS Codeのインストール

インストーラーを使用し、VS CodeをWindowsにインストールします。

2.4.3. 拡張機能

VS Codeに基本的な拡張機能をインストールします。

2.4.4. エディターの設定

ファイル > ユーザー設定 > 設定と移動し、エディターの設定を変更します。私の場合は以下のように変更しました。

  • ウインドウのタイトルにファイルの絶対パスを表示する
    • Window: Title${dirty}\${activeEditorLong}${separator}${rootName}に変更する
  • 空白文字を常に表示する
    • Editor: Render Whitespaceall に変更する
  • ミニマップの表示領域を常に表示する
    • Editor > Minimap: Show Slideralways に変更する
  • ツリーのインデントを深く設定する
    • Workbench › Tree: Indent16 に変更する
  • インデントガイドを常に表示する
    • Workbench › Tree: Render Indent Guidesalways に変更する
  • 角かっこのペアの彩色とブラケットペアのガイドを有効にする
    • Editor › Bracket Pair Colorization: Enabled をチェックする
    • Editor › Guides: Bracket Pairstrue に変更する
  • 目次に含める見出しレベルを変更する
    • Markdown › Extension › Toc: Levels1..2 に変更する

2.4.5. WSL2-Ubuntuへの接続

WindowsからVS Codeを介してWSL2-Ubuntuに接続できるように設定します。さて、Microsoft docsには以下のような記載があります。

一部の WSL Linux ディストリビューションには、VS Code サーバーの起動に必要とされるライブラリが不足しています。(中略)wget (Web サーバーからコンテンツを取得するため) と ca-certificates (SSL ベースのアプリケーションで SSL 接続の信頼性を確認するのを許可するため) を追加するには……(後略)

そこで、以下のコマンドを実行し、Ubuntu 20.04 LTSに wgetca-certificates がインストール済みかどうか、確認します。

bash
apt list --installed | grep -E 'wget|ca-certificates'

【実行結果】

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

ca-certificates/focal-updates,focal-security,now 20210119~20.04.2 all [installed,automatic]
wget/focal-updates,now 1.20.3-1ubuntu2 amd64 [installed,automatic]

Ubuntu 20.04.4 LTSには wgetca-certificates がインストール済みであることが確認できました。

以下のコマンドを実行し、WSL2-UbuntuからVS Codeを起動します。

bash
code .

【実行結果】

Installing VS Code Server for x64 (c722ca6c7eed3d7987c0d5c3df5c45f6b15e77d1)
Downloading: 100%
Unpacking: 100%
Unpacked 1619 files and folders to /home/UserName/.vscode-server/bin/c722ca6c7eed3d7987c0d5c3df5c45f6b15e77d1.

初回の接続では、VS Code ServerがWSL2-Ubuntuにインストールされます。Windows側のVS Codeはインターフェースの役割をし、WSL2-Ubuntu上のVS Code Serverが仕事をする、といったところでしょうか。

2.4.6. WSL2のDNS設定変更

WSL2の既知の問題で、IPネットワーク上でドメイン名とIPアドレスの対応関係を解決するドメインネームシステム(DNS)の設定ファイル /etc/resolv.conf/ がおかしくなり、ネットワークに接続できなくなることがあります。根本的な原因は不明のようですが、設定ファイルの自動生成を停止してDNSを設定することで、問題を回避できます。

まず、WSL2をシャットダウンします。

PowerShell
wsl --shutdown

WSL2の起動時に、DNSの設定ファイル /etc/resolv.conf/ が自動で生成されて上書きされてしまうので、生成を停止します。/etc/wsl.conf を作成して以下の内容を追記します。

bash
sudo nano /etc/wsl.conf

【追記内容】

/etc/wsl.conf
[network]
generateResolvConf = false

次に、既存の/etc/resolv.conf を削除して、シンボリックリンクを一度削除します。

bash
sudo rm /etc/resolv.conf

/etc/resolv.conf を作成してDNSを設定します。今回はGoogle Public DNSにしました。もちろん、ホストであるWindowsでコマンドプロンプトから ipconfig でDNSサーバ名を確認し、/etc/resolv.conf に記載することでも問題ありません。

bash
sudo nano /etc/resolv.conf

【追記内容】

/etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4

とくにWSL2の再起動をしなくても、DNS設定が反映されます。

2.5. Gitをインストールして設定する

2.5.1. 参照したドキュメント

2.5.2. Windows側の設定

はじめに、GitHubのアカウントを作成しておきます。次に、WindowsにGit for Windowsをインストールします。基本的にはデフォルトの設定のまま進めますが、以下の項目は変更します。

  • "Choosing the default editor used by Git" ではVS codeを選択する
  • "Enable Git Credential Manager" にチェックを入れて有効化する
  • "Enable symbolic links" にチェックを入れて有効化する

インストールが完了したら、Windows TerminalでもGit Bashを使えるように、新たなプロファイルを追加し、以下のように設定します。

  • 名前 Git Bash
  • コマンドライン C:\Program Files\Git\bin\bash.exe
  • 開始ディレクトリ %USERPROFILE%
  • アイコン C:\Program Files\Git\mingw64\share\git\git-for-windows.ico

Git Bashで以下のコマンドを実行し、Gitのユーザー名とメールアドレスを設定します。GitHubで使用しているものと同じ設定にしました。

Git Bash
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"

2.5.3. WSL2-Ubuntu側の設定

WSL2-Ubuntuのbashでも同様にGitのユーザー名とメールアドレスを設定します。

bash
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"

WSL2-UbuntuでWindowsのGit Credential Manager(GCM)を使用するよう設定します。この設定をすることで、毎回認証要求をされずに済みます。

bash
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager-core.exe"

2.6. makeをインストールする

2.6.1. 参照したドキュメント

2.6.2. makeとは

makeは、プログラムのビルド作業を自動化するツールのひとつで、make コマンドに実行させる手順を記述したテキストファイルをMakefileといいます。makeはファイルの依存関係を考慮しつつコンパイルを自動化するために開発されたツールですが、材料から何かを作るためのルールを記述する、一般的なツールとしても使用できます。今回はdockerの起動コマンドを短縮する目的で使用します。

2.6.3. makeのインストール

Ubuntu 20.04.4 TLSにはデフォルトで make がインストールされていないので、以下のコマンドでインストールします。

bash
sudo apt update && sudo apt upgrade
sudo apt install make

makeのバージョンを表示し、正しくインストールされたことを確認します。

bash
make --version

【実行結果】

GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

3. Rプロジェクトを作成する

3.1. 参照したドキュメント

3.2. Rプロジェクトのひな型

DockerとRの renv パッケージを使用したRプロジェクトのひな型を、MITライセンスで公開された方がいますので、こちらを参考としてRプロジェクトを作成します。私の場合は、論文の執筆に向いた特徴を備えている checkpoint をパッケージ管理に使用しているため、Rプロジェクトの構成を大きく変更しました。詳細は以下の記事にまとめました。

3.3. リポジトリの作成とクローン

私は ~/res ディレクトリを作成し、その下に各研究のRプロジェクトを配置することにしました。

bash
cd
mkdir res

この記事では、テスト用に 2203_test というプロジェクトを作成します。まずはひな型の説明に従い、GitHubでUserName/2203_test リポジトリを作成後、 WSL2-Ubuntuの ~/res ディレクトリにクローンします。クローンする際、初回ログインの場合はGCMの認証が求められます。

bash
cd res
git clone https://github.com/UserName/2203_test.git

【実行結果】

Cloning into '2203_test'...
info: please complete authentication in your browser...
remote: Enumerating objects: 33, done.
remote: Counting objects: 100% (33/33), done.
remote: Compressing objects: 100% (23/23), done.
remote: Total 33 (delta 0), reused 23 (delta 0), pack-reused 0
Unpacking objects: 100% (33/33), 14.51 KiB | 874.00 KiB/s, done.

~/res/2203_test ディレクトリが作成されました。これがそのままひとつのRプロジェクトです。ディレクトリの構造を確認するために、tree パッケージをインストールします。

bash
sudo apt update && sudo apt upgrade
sudo apt install tree

以下のコマンドを実行し、~/res ディレクトリから4階層の構造を表示します。

bash
tree -a -F -L 4 ~/res

【実行結果(一部編集しています)】

~/res
└── 2203_test/
    ├── .Rprofile.
    ├── .Rprofile          【R:セッション開始時に実行するスクリプト】
    ├── .checkpoint/       【R:checkpointによるパッケージキャッシュ】
    ├── .env.example       【Docker Compose:環境変数の設定テンプレート】
    ├── .git/
    ├── .gitignore
    ├── LICENSE
    ├── Makefile           【Make:起動コマンド短縮】
    ├── README.md
    ├── codes/
    │   ├── .gitignore
    │   ├── README.md
    │   ├── analysis.qmd   【Quarto:解析コードと結果の解釈】
    │   ├── analysis_cache/
    │   ├── analysis_files/
    │   ├── datasets/      【Quarto:データセット】
    │   ├── figures/       【Quarto:プロットの画像データ(.svg)】
    │   └── templates/     【Quarto:引用文献の書誌要素とスタイル定義】
    ├── compose.yml        【Docker Compose:設定ファイル】
    ├── dev/
    │   ├── docker/
    │   │   ├── .Renviron
    │   │   ├── .ssh/
    │   │   ├── Dockerfile 【Docker:設定ファイル】
    │   │   └── startup.sh*
    │   └── dotfiles/     【RStudio:設定ファイル】
    └── research.Rproj     【R:Rプロジェクトファイル】

4. VS codeからRStudio Serverを実行する

4.1. 参照したドキュメント

4.2. 起動と終了

Rプロジェクトを配置したディレクトリ(Makefileのある場所…今回は ~/res/2203_test)で make up コマンドを実行すると、バックグラウンドでRStudio Serverを起動します。ブラウザからRStudio Server (http://localhost:8787/) にアクセスすれば、解析が開始できます。同様に、make down で終了、make でコマンドのヘルプを閲覧できます。

【起動】

bash
make up

【実行結果(抜粋)】

[+] Building 0.3s (12/12) FINISHED
[+] Running 1/0
 ⠿ Container r-project-rstudio-1  Running        0.0s
💡 Access: http://localhost:8787/

【終了】

bash
make down

【実行結果】

[+] Running 2/2
 ⠿ Container r-project-rstudio-1  Removed       11.8s
 ⠿ Network r-project_default      Removed        0.7s

【ヘルプを開く】

bash
make

【実行結果】

Command list:
[Target]  [Description]                                    [Product]
help      show a command list                              N/A
up        build and run RStudio Server in the background   docker compose up -d --build
down      stop and remove running containers and networks  docker compose down
stop      stop running containers without deleting it      docker compose stop
start     (re-)start stopped containers                    docker compose start
ps        list containers for the compose-project          docker compose ps
prune     delete unused Docker objects                     docker system prune -f
bash      start bash in the rstudio container              docker compose exec rstudio /bin/bash

4.3. 解析結果の再現手順

以下の手順で解析結果を再現できます。

  1. 最新のDocker EngineとDocker Composeが使用可能か確認し、必要に応じてインストールする
  2. git コマンドと make コマンドが使用可能か確認し、必要に応じてインストールする
  3. 適当なディレクトリに、 git clone コマンドでRプロジェクトをコピーする
  4. .env.example をコピーし、.env を作成する(オプション)
  5. Docker daemonが起動している状態で、Rプロジェクトのディレクトリで make up コマンドを実行し、RStudio Serverを起動する
  6. Rプロジェクトを開いてから、codes ディレクトリ内の analysis.qmd で解析を実行する
  7. 解析が終わったら make down コマンドを実行し、終了!

以下の内容は統計解析には必須ではありません。Zennの設定です。

5. Zenn関連の設定(オプション)

5.1. ZennとGitHubを連携し、Zenn CLIをインストールする

5.1.1. 参照したドキュメント

5.1.2. リポジトリの作成とクローン

GitHubに新規のリポジトリ UserName/zenn を作成します。コンテンツは空で、README.mdも不要です。bashで以下のコマンドを実行し、WSL2-Ubuntuのホームディレクトリにクローンします。

bash
cd
git clone https://github.com/UserName/zenn.git

~/zenn ディレクトリが作成されました。

5.1.3. Node.jsとZenn CLIのインストール

Zennのコマンドラインインターフェイス(Zenn CLI)は、サーバー側で動くJavaScript実行環境の1つ:Node.jsを使用しているため、まずはNode.jsをWSL2-Ubuntuにインストールします。以下のコマンドを実行し、Node Version Manager(通称nvm)をインストールします。

bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

続いて、以下のコマンドを実行し、nvmを読み込みます。

bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

以下のコマンドを実行し、nvmが正しくインストールされたことを確認します。インストールに問題が無ければ nvm と表示されます。

bash
command -v nvm

【実行結果】

nvm

Node.jsのインストールにはC言語のコンパイラが必要になりますが、初期状態のUbuntu 20.04.4 LTSにはCコンパイラが含まれていないので、gcc をインストールします。

bash
sudo apt install gcc

安定バージョンのNode.jsをインストールします。最新のバージョンを共存させることもできますが、今回は省略します。同時にNode Package Manager(通称npm)もインストールされます。

bash
nvm install --lts

Node.jsとnpmのバージョンを表示し、インストールされたことを確認します。

bash
node --version
npm --version

~/zenn ディレクトリに移動し、npmでプロジェクトを初期化し管理下に置きます。

bash
cd zenn
npm init --yes

~/zenn ディレクトリにZenn CLIをインストールします。

bash
npm install zenn-cli

続いて、npxコマンドでローカルにインストールしたZenn CLIのバイナリを実行し、必要なディレクトリとファイルを作成すれば、導入完了です。

bash
npx zenn init

5.1.4. 記事の作成

~/zenn ディレクトリで以下のコマンドを実行すると、~/zenn/articles ディレクトリに what-is-slug.md が作成されます。

bash
npx zenn new:article --slug what-is-slug

slug(スラッグ)はZennのコンテンツのユニークなIDで、https://zenn.dev/ユーザー名/articles/what-is-slug というように、記事のURLにも含まれます。

~/zenn ディレクトリで以下のコマンドを実行し、http://localhost:8000にブラウザで接続すると記事のプレビューを閲覧できます。

bash
npx zenn preview

【実行結果】

👀 Preview: http://localhost:8000

以上で、WSL2 + Docker + VS CodeでRの解析環境が整いました。

Discussion