はじめに
Windows10 で Node.js を使った開発をしています。
チームメンバーは自分以外全員 Mac で、みんなビルドが早いです。
最近自分の PC を新しくしましたが、やはり自分のほうが遅いのです。スペックはみんなのより上なはずなのに。
Windows でやるから遅いのかもしれないと思い、Linux で開発環境を作ってみようと思いました。
対象者
- Linux や Docker の基礎知識がある方
環境
- Windows10
- WSL2
- Ubuntu
- Docker CE
Docker Desktop は使いませんでした。
Windows10 に WSL2 を導入し Ubuntu をインストールします。
その Ubuntu に Docker を利用できる環境を作りました。
ここまでは Docker を利用するのに必要なので、準備済みとして進めます。
開発環境に入れたいもの
以下が開発環境に入れておきたいものです。
- Node.js
- git
- zsh
- Vim
- Go
入れたいものは他にもありますが多いため割愛しました。
作る開発環境について
続いてどこに何を置くかです。
Windows | Ubuntu | Dockerコンテナ | |
---|---|---|---|
入れる物 | VSCode | プロジェクトのソースコード | に書いた入れたいもの |
- Windows の VSCode を使ってソースコードを書きます
- ソースコードは Ubuntu に置きます
- Windows にはソースコードや開発環境は置きません
- 開発で使用するコマンド等は Docker コンテナに入って実行します
- Ubuntu で起動した Docker コンテナに接続して利用する想定です
- ビルド結果のファイルなど新たに作成されるファイルは Ubuntu 領域に保存します
パーミッションに注意
ここまで説明した構成をそのまま作るとパーミッション周りで不都合が発生します。
たとえば Docker コンテナで git clone
したソースファイルを VSCode で保存すると Permission Denied
で怒られます。Docker コンテナではデフォルトが root なようでこれが原因です。
Ubuntu と Docker コンテナのユーザーを揃える必要がありそうなので、今回は Docker コンテナで使うユーザーを Ubuntu に合わせようと思います。
1つのコンテナでいろいろやりたい
△△の作業はコンテナ A で、□□の作業はコンテナ B で、のように都度コンテナを切り替えるのは嫌なので、必要なもの全部入りのコンテナを作ります。
Dockerfile
以下のような Dockerfile
を書きました。
FROM ubuntu:21.10
# 使用するユーザーやバージョンを指定
ARG USER_NAME=kyamadahoge
ARG USER_ID=1000
ARG GROUP_ID=1000
ARG NODE_VERSION=14.18.3
ARG GO_VERSION=1.16.10
# apt で入れたいものをインストール
RUN apt update && apt install -y \
zsh \
git \
vim \
&& apt clean \
&& rm -rf /var/lib/apt/lists/*
# rootパスワードの設定と一般ユーザーを作成
SHELL ["/bin/bash", "-c"]
RUN echo "root:root" | chpasswd && \
addgroup --gid ${GROUP_ID} ${USER_NAME} && \
adduser --shell /bin/zsh --uid ${USER_ID} --gid ${GROUP_ID} --disabled-password --gecos "" ${USER_NAME} && \
echo "${USER_NAME}:${USER_NAME}" | chpasswd && \
echo "%${USER_NAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/${USER_NAME} && \
chmod 0440 /etc/sudoers.d/${USER_NAME}
# Node.jsインストール
WORKDIR /usr/local
RUN curl -L https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz -o node.tar.gz \
&& mkdir node \
&& tar zxf node.tar.gz -C node --strip-components 1 \
&& rm node.tar.gz \
&& ln -s /usr/local/node/bin/node /usr/bin/node
ENV PATH="/usr/local/node/bin:${PATH}"
# Goインストール
RUN curl -L https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz -o go.tar.gz \
&& tar -xzf go.tar.gz \
&& rm go.tar.gz
ENV PATH="/usr/local/go/bin:${PATH}"
# 一般ユーザーに切り替え
USER ${USER_NAME}
- イメージのサイズをなるべく減らせるように、apt キャッシュを削除しておくと良いそうです
- RUN 命令をなるべく少なくすることで、イメージを構成するレイヤーが減ってパフォーマンスが向上するそうなので、コマンドを連結して記述しました
- ここでは見やすさのために RUN を分けて実行していますが、一発でやる方がより良いと思います
- パーミッション問題対策で、Docker コンテナで使用するユーザーと Ubuntu のユーザーの ID を合わせます
- Dockerfile 内の
USER_ID
、GROUP_ID
の値を Ubuntu で使用するユーザーの ID と合わせます
- Dockerfile 内の
docker-compose.yml
最低限しか書いてないため、このファイルは無くても良いかもしれません。
コンテナの起動が楽なので作りました。
version: '3.3'
services:
dev:
build: .
volumes:
- type: bind
source: ./apps
target: /apps
tty: true
- Docker コンテナ内の
/apps
と Ubuntu の docker-compose.yml を置いたディレクトリ(*1)内のapps
ディレクトリとが同期されます- ここにプロジェクトで使用するソースファイル等を配置します
- 例えば (*1) が
/home/kyamadahoge/proj
なら- Ubuntu の
/home/kyamadahoge/proj/apps
と - Docker コンテナの
/apps
が同期します
- Ubuntu の
- VSCode で
/home/kyamadahoge/proj/apps
以下のファイルを編集し、Docker コンテナで/apps
以下に対しビルド等をするということです
- 起動したコンテナをすぐに終了させないために
tty: true
を記述しています
コンテナ起動
上記 2 ファイルを同じディレクトリに置いて
docker-compose up -d
でイメージが仕立てられて、コンテナが起動します。続いて
docker-compose exec dev zsh
でコンテナに入れるので、ここでビルドなど開発作業を行います。
肝心のビルド時間は?
Windows と Docker コンテナで同じリビジョンのソース一式をビルドしました。
Windows | Docker | 速度 | |
---|---|---|---|
プロジェクトA | 69秒 | 31秒 | 2.23倍 |
プロジェクトB | 142秒 | 50秒 | 2.84倍 |
Windows よりもかなり改善されました!やった
所感
同じ PC でこんなに違うのかと驚きました。ビルド速度が改善できて良かったです。
ミドルウェアのバージョンを切り替えて開発する場合には、別バージョンを入れたコンテナを別途作れば簡単に切り替えができて良いなと思いました。
もっと使い込んでいきたいと思います。