docker + VScodeで開発環境作り (Docker Desktopを使えない人向け)

## 0. まえがき
docker、便利ですよね。研究室で渡されたDockerfileを使って環境を作りをして、すぐにできるんだなあと感心したものです。当初は何が起こっているかよくわかっていませんでしたが。

dockerについての説明は言語が苦手な僕がやってもしょうがないので、「docker 入門」とかでググっていただければ、分かりやすい記事がたくさんあるのでその辺でイメージを膨らませてくれたらと思います。

会社でLinuxの開発環境がほとんどないので、WindowsでDocker Desktopを使っていたんですけど、いつの間にやら有料化されていて、ビジネスでは使えなくなっていました。しかもこれ、開発環境としてとか、試験的に使うとかもダメなようで、脱Docker Desktopを余儀なくされました・・・。（便利だったのに）

というわけで、Docker Desktopなしでdocker＋VScodeの環境作りをしたので、忘れないようにメモを残しておきます。社内でdockerを流行らせるための資料にしようと思っていたのですが、案外需要があるかもしれないので、Qiitaに載せておきます。初投稿ですのでお手柔らかにお願いします。

概念や処理の意味など詳細は省いているので、参考文献を見てみることをおすすめします。どこかでエラーが起きたときも、参考文献からあたってみるとよいかと思います。（丸投げ）


## 1. WSLの有効化
まず、WSLを有効にします。

Windows Powershellを管理者権限で開いて、
```PowerShell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
PCを再起動した後、WSL2をデフォルトに設定。
```PowerShell
wsl --set-default-version 2
```

### 参考文献
+ https://qiita.com/rubytomato@github/items/a290ecef2ea86ea8350f

## 2. Ubuntuのインストール
ベースとなるLinuxディストリビューションをインストールします。この上にコンテナが載るイメージです。

WindowsボタンからMicrosoft Storeを開きます。
”Ubuntu”で検索します。とりあえずUbuntuがやりやすいと思います。

「入手」ボタンを押してUbuntu 22.04 LTSをインストールします。

起動すると、ユーザの作成を要求されます。ユーザ名はデフォルトではユーザ名になるはず。なんでもいいけど。

aptを最新の状態に更新しておきます。
```Ubuntu
sudo apt update && sudo apt upgrade -y
```

インストールの確認には、コマンドプロンプトを開いて、
```cmd
wsl --list --verbose
```
で確認できます。STATUSがRunningであることとVERSIONが2であることを確認します。

Ubuntuを起動するときは、スタートメニューからUbuntu22.04を選択すればOK。これを開発環境とすることも可能ですが、複数プロジェクトでLinuxを使う際に依存関係の問題で不便になる可能性もあるので、ここはなるべくいじらずに、Dockerで環境を構築しましょう。

### 参考文献
+ https://qiita.com/rubytomato@github/items/a290ecef2ea86ea8350f

## 3. Dockerのインストール
とにかくDockerが無いと始まらないので、先ほどのUbuntuの中にDockerをインストールしましょう。
```bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
sudo apt update
sudo apt install docker-ce
sudo service docker start
sudo mkdir -p /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
sudo curl -L https://github.com/docker/compose/releases/download/1.26.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo gpasswd -a $USER docker
sudo chgrp docker /var/run/docker.sock
sudo service docker restart
exit
```
これで環境構築と設定はOKのはずです。以下動作確認。
```bash
docker run hello-world
docker images
docker ps
```
正しく動けばOK。

自分がやった時はdocker daemonが起動しない問題が発生していたので、そうなったときはUbuntu上で、
```bash
sudo update-alternatives --config 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
```
ここで`1`を選びます。Ubuntu 22.04だと起こるっぽい。

いちいちUbuntuを開いて`sudo service docker start`を叩くのが面倒なので、自動で走ってもらえるようにします。（Windows11なら、これをするとエラーになった。かつ、しなくても自動で走ってくれるっぽい）
```bash
echo 'none none rc defaults 0 0' | sudo tee -a /etc/fstab
echo '#!/bin/bash' | sudo tee /sbin/mount.rc
sudo chmod +x /sbin/mount.rc
echo 'service docker start' | sudo tee -a /sbin/mount.rc
echo 'mkdir -p /sys/fs/cgroup/systemd && mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd' | sudo tee -a /sbin/mount.rc
```
確認するときは、コマンドプロンプトから、wslを再起動して、
```cmd
wsl --shutdown
wsl
```
立ち上がったUbuntuで、
```bash
sudo service docker status
```
を叩いて実行中になっていればOK。


### 参考文献
+ https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-ja
+ https://qiita.com/amenoyoya/items/ca9210593395dbfc8531#docker%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89
+ https://zukucode.com/2019/04/docker-hello-world-run.html
+ https://qiita.com/amenoyoya/items/41a2334cbc1facb87864
+ https://marukot-ch.hatenablog.com/entry/2023/12/07/220237 (Windows11のときにエラー)

## 4. VScodeのインストール
そもそも高機能エディタを持ってない人はこの機会にVScodeを入れておきましょう。\
以下VScode向けに書きますので、宗派の違う人は教義に従って対応してください。

まずは本体から
+ https://code.visualstudio.com/

全てデフォルトで問題ないはずです。

拡張機能を追加します。追加するにはサイドバーから拡張機能アイコン(□が4つあるやつ)を選択するか、`Ctrl+Shift+x`を押します。\
以下、記憶が曖昧なので足りなかったらごめんなさい。必要になるタイミングで入れてもらえたらと思います。
+ Japanese Language Pack for Visual Studio Code (日本語化)
+ Remote-WSL
+ Remote-Container

### 参考文献
+ https://zenn.dev/kcabo/articles/c4f9b7fecc503a

## 5. Dockerfileの作成
ここからがDockerの肝です。作りたい環境をDockerfileに記載して、それをビルドすることで簡単に開発環境ができてしまいます。\
簡単にDockerfileの一例を乗せます。どこか開発環境にしたいフォルダに"Dockerfile"ファイルを作成してみてください。
```Dockerfile
FROM ubuntu:20.04

RUN apt update

RUN apt -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt install -y vim less
RUN apt install -y python3.9

RUN python3.9 -m pip install numpy
```
Ubuntu20.04を持ってきて、そこから環境を追加しています。必要な環境をここに記述していれば、チームメンバー全員が同じ環境で開発することができます。最初は足りないものがあっても後から足せますので自分だけのコンテナであれば厳密に書かなくても大丈夫です。

### 参考文献
+ https://knowledge.sakura.ad.jp/15253/

## 6. Docker imageのビルド
Dockerfileができたらビルドしましょう。Ubuntuを開いて、Dockerfileがあるディレクトリに移動します。WSLではWindowsドライブが`/mnt`にマウントされているので、\
`/mnt/c/Users/(ユーザ名)/Documents/(開発フォルダ)` くらいでしょうか。cdでそこまで移動して、
```bash
docker build -t sample:1 .
(docker build [ -t ｛イメージ名｝ [ :｛タグ名｝ ] ] ｛Dockerfileのあるディレクトリ｝)
```
ビルドが終わったら、
```bash
docker images
```
を実行すると、ビルドしたdocker imagesが一覧表示されるはずです。\
ビルドエラーが起きたら、根気よくDockerfileを直してください。

### 参考文献
+ https://qiita.com/quzq/items/1096c638c0d86795be13
+ https://atmarkit.itmedia.co.jp/ait/articles/1407/08/news031.html

## 7. Docker Containerの作成
上で作成したdocker imageを実際に動かしてみましょう。Ubuntu上で、
```bash
docker run -it sample:1
```
これで動作します。同時にコンテナの中に入ってrootでログインした状態になります。
OSのバージョンがDockerfileに記載した通りになっているはずです。
コンテナから抜けるには、Ctrlキーを押しながら、PキーとQキーを順番に押します。`exit`で抜けると、コンテナが停止するので注意してください。停止したコンテナは`docker start`で起こせます。

動作中のコンテナを確認するには、コンテナ外で、
```bash
docker ps
```
を叩いて、一覧表示を確認します。停止中のコンテナも一覧表示させたいときは、`-a`のオプションを付けます。

開発環境として便利にするために、開発用フォルダをコンテナから参照できるようにします。\
`docker run`をする際に、`-v`のオプションでフォルダをマウントできます。

```bash
docker run -it -v /mnt/c/path/to/(開発環境フォルダ):/mnt sample:1
```
とすることで、開発環境フォルダの中身がコンテナ内の`/mnt`に反映されるようになり、コンテナからの変更がwindows側の開発環境フォルダにも反映されるようになります。

Webを使うシステムの場合は、Windows側のマシンのポートをコンテナに振ってやる必要があります。
その時は`-p`のオプションを使って、`-p 3000:8080`のように記述すると、`localhost:3000`でコンテナ内部の8080番にアクセスすることができます。\
これを使うことで様々なWebシステムを複数コンテナで同時に稼働させてポート番号でシステムを割り振る、みたいな器用な運用ができます。


### 参考文献
+ https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53
+ https://qiita.com/tbpgr/items/5ff706ce2c62bffafd88
+ https://qiita.com/hirokihello/items/69df88ba55125c2aed39

## 8. VScodeのアタッチ
基本の開発環境は完成しましたが、このままだとプログラムを実行するのにいちいちコンテナ内部のbashでコマンドをたたいてやる必要があるので、VScodeから実行できるようにしましょう。\
まずはVScodeでWSLを開きます。拡張機能のRemote WSLがインストールされていると、左下に≶マークが表示されているのでそこをクリックして、「新しいWSLウインドウ」を選択します。\
この時、Remote Containerのメニューも選択できますが、これを使用するにはDocker Desktopが必要になってきますので、個人なら問題ないですが、会社のPCには向きません。

WSLウインドウが表示されたら、もう一度左下の≶マークをクリックして、「Atatch to Running Container」を選択します。実行中のdockerコンテナ一覧が表示されるので、開発で使用するコンテナを選択します。今回は先ほど3でインストールしたdockerを使用するので、Docker Desktopは必要ありません。

コンテナにアタッチして左下の≶マークの横にイメージ名(コンテナ名)が表示されれば環境構築は完了です。後は作業に使うフォルダを開いておいて、ワークスペースを保存しておけばPCを起動後すぐに開発環境にたどり着けるのでおすすめです。

PC起動後最初にワークスペースを開くと、コンテナが止まっているのでアタッチできないのですが、警告からStart Containerを選択できるので、VScodeを開いてワークスペースを開くだけで開発開始できます。

参考文献
+ https://qiita.com/_masa_u/items/d3c1fa7898b0783bc3ed
+ https://zenn.dev/kcabo/articles/c4f9b7fecc503a