【Docker】Node.jsのコンテナを作成する
パンジェンシ氏「東の森でシステムエンジニアをしております、パンジェンシーと申します。
最近は、とにかく情報が多すぎて覚えていられないので、細かい内容もできるだけメモに残しておこうと思います。
」
Node.jsのインストール再び!
5年前くらいのエントリーで、「Node.jsをインストールしてみよう!」的なことをやりました。
その後状況がだいぶ変わっていると思いますので、やり方を調べてよさげなものをメモしておきます。
1. Node.jsをインストール?
現在の私の環境は、Windows 10 HomeにWSL2を使ってUbuntu 20.04 LTSを入れているような状態で、このUbuntuにNode.jsをインストールしてみたいと思います。
デーヴァ「せっかくDockerを入れたんだから、Node.jsがインストールされたDockerイメージを使えばすぐなのデヴァ?」
パンジェン氏「た…たしかに…。そのためのDockerですよね…。(何でデーヴァさんがここに…?)」
2. Node.jsのDockerコンテナを作成
というわけで、Node.jsを直接ホストOSにインストールするのはやめて、Node.jsのDockerコンテナを作ってみましょう!
ディレクトリとファイルを作成
まずは、必要なディレクトリとファイルを作成します。
// どこか適当なディレクトリで以下のように $ mkdir node-app-sample && cd node-app-sample $ touch docker-compose.yml $ mkdir src $ touch src/server.js // こんな感じの構成になります。 任意のディレクトリ └── node-app-sample ├── docker-compose.yml └── src └── server.js
このserver.jsというファイルに、Node.js公式ページのサンプルを貼り付けます。
const http = require("http"); const hostname = "127.0.0.1"; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader("Content-Type", "text/plain"); res.end("Hello World"); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
3行目のhostname
が127.0.0.1
(ローカルホスト)となっていますが、この設定ではホストマシンからコンテナにアクセスできません。
調査の結果、0.0.0.0
と設定しておけばアクセスできるようです。この'0.0.0.0'と設定すると「ホスト内の全てのIPアドレスで待受る」という意味になります。
const http = require("http"); - const hostname = "127.0.0.1"; + const hostname = "0.0.0.0"; const port = 3000;
Docker Composeファイルは以下のようにしてみます。
version: "3" services: app: image: node:lts # イメージを取得 container_name: node # コンテナの名前を設定 volumes: # ディレクトリをリンク - ./src:/app/src # [ホスト側]:[コンテナ内] ports: # 公開用ポート設定 - 3001:3000 # [ホスト側]:[コンテナ内] command: node server.js # コンテナ起動時に実行するコマンド working_dir: /app/src # コマンドを実行するディレクトリ
コンテナの作成
では、コンテナをビルドしてみましょう。docker-compose.yml
の置いてあるディレクトリで以下を実行します。
$ docker-compose build
ビルドが終わったら、コンテナを起動してみましょう。
$ docker-compose up -d
コンテナの内部でserver.jsのプログラムが起動しているかログを確認してみましょう。
$ docker-compose logs
以下のようなログが表示されていればOKです。エラーが起きている場合はコードを見直しましょう。
Attaching to node
node | Server running at http://0.0.0.0:3000/
ブラウザからhttp://localhost:3001にアクセスしてみましょう。
無事、「Hello World」が表示されたでしょうか?
「コンテナ内では3000ポートで起動していますが、docker-compose.yml
で公開用ポートを3001に設定したので、3001でアクセスしなければいけないことに注意しましょう。」
まとめ
今回はNode.jsのコンテナを作成してサンプルプログラムを実行してみました。
これを応用して、色々なフレームワークのコンテナを作成して動かしてみようと思います。
【Docker】MySQLのコンテナを作成する
パンジェン氏「東の森でシステムエンジニアをしております、パンジェンシーと申します。
最近ずっと家に籠もりっぱなしなので、お腹の脂肪が大変なことになっております。」
RDB環境を構築してみよう
学習用などに自由にイジれるデータベース環境が一つあると便利ですよね。Dockerを使えば、環境構築や廃棄が簡単にできそうなのでちょっと試してみました!
今回は、MySQLのコンテナを作成してみます。MySQL(まい・えすきゅーえる)は、オープンソースのリレーショナルデータベース管理システム(RDBMS)(Wikipediaより)の一つで、無料で使えて、世界中の多くのシステムで採用されているそうなので、これを使うことにします。
「SQL(Structured Query Language)は、RDB(Relational Database)のデータを操作するための言語です。」
1. MySQLのコンテナを作成
Dockerを導入していない場合は、以下のエントリー⇩を参考に導入してみてください。
導入できたら、WSL2のターミナルに入りましょう。
今回は、Docker Composeというツールを使ってみましょう。このツールを使うと、イメージの作成方法やコンテナの設定などをファイルに残しておくことができます。今回はコンテナは1つですが、複数のコンテナを同時に管理する時にとても便利なのでぜひ使い方をマスターしておきましょう。
// 適当なディレクトリを作成 $ mkdir -p practice-mysql && cd practice-mysql // 設定ファイルを作成 $ touch docker-compose.yml
mysql
というディレクトリにdocker-compose.yml
という設定ファイルを作成しました。今度は、エディターからこのファイルを開いて以下の内容を追加しましょう。
version: "3" services: mysql: # サービス名 image: mysql:latest # 基にするDockerイメージ container_name: db-mysql # 作成するDockerコンテナの名前 volumes: - .:/home/pangency # 現在のパス'.'と、コンテナ内の'/home/pangency'をリンク environment: - MYSQL_ROOT_PASSWORD=root # rootパスワードを設定
// 上の設定は、下のコマンドとほぼ同様の意味になります。
$ docker run --name db-mysql \
-e MYSQL_ROOT_PASSWORD=root \
-v .:/home/pangency \
-d mysql:latest
volumes
というところに、.:/home/pangency
と記載していますが、これは、:
の左側にホスト内のパス、右側にコンテナ内のパスを設定し、これらの場所をリンクする設定です。
今回の場合、.
は現在のパスという意味なのでdocker-compose.ymlが置いてあるpractice-mysql
ディレクトリ、右側がコンテナ内のパス/home/pangency
になり、これらをリンクするという設定になります。後で本当にリンクされているか確認してみましょう。
ファイルを保存したら、Dockerイメージを作成します。
// `docker-compose.yml`を保存したディレクトリで以下を実行します。 $ docker-compose build // `skipping`などのメッセージが出た場合は、既に同じ内容のDockerイメージを持っているということなのでOKです。
イメージが作成できたか確認してみましょう。
// イメージの一覧を表示 $ docker-compose images Container Repository Tag Image Id Size --------------------------------------------------------- db-mysql mysql latest 6e447ce4863d 544.2 MB // 上のような感じで作成できていればOKです!
次にコンテナを起動してみます。
// コンテナの起動 $ docker-compose up -d // コンテナ一覧の表示 $ docker-compose ps Name Command State Ports -------------------------------------------------------------------- db-mysql docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
無事起動できました!
「Docker Composeで作成したコンテナを終了する場合は、docker-compose stop
、コンテナを終了して削除する場合は、docker-compose down
を実行しましょう。削除した場合は、データベースの内容も全て消えてしまうので注意してください!」
2. コンテナにログイン
コンテナにログインしてみましょう。
$ docker-compose exec mysql bash
コンテナ内でディレクトリを移動してみましょう。
# cd home/pangency # ls
ここに、先程作成したdocker-compose.yml
があるのではないかと思います。
volumes
に.:/home/pangency
と設定をしたことによって、ホスト側とコンテナ内のディレクトリをリンクできています。この機能を使えば、例えばホスト側で作成したsqlファイルを設置し、コンテナ内で実行することができます。
「コンテナ内からログアウトしてホストのターミナルに戻りたい場合は、exit
コマンドを実行しましょう。」
3. データベースの作成
コンテナ内からデータベースを作成してみましょう。
コンテナ内でmysqlコマンドを実行してCUIツール「MySQLモニター」を起動します。
# mysql -u root -p mysql>
以下のコマンドを売って、データベースpractice
を作成してみます。
mysql > create database practice; mysql > show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | practice | | sys | +--------------------+ 5 rows in set (0.00 sec)
practice
という名前のデータベースが作成されました!
「MySQLモニターを終了したい場合は、quit
を実行しましょう。exit
ではないので注意です!」
4. テーブルの作成
無事、データベースが作成できたので、テーブルを作ってみましょう!ホスト側から以下のファイルを作成します。
// docker-compose.ymlのあるディレクトリにファイルを作成
$ touch create-table.sql
中身は何でもよいですが、今回は以下のような感じにします。エディターで編集しましょう。
-- テーブルが既にある場合は一旦削除 DROP TABLE IF EXISTS tasks; -- テーブルの作成 CREATE TABLE tasks ( id int primary key, title varchar(50), create_date datetime, create_person varchar(30) ); -- データの挿入 INSERT INTO tasks (id, title, create_date, create_person) VALUES (1, 'read a book', sysdate(), 'pangency'); INSERT INTO tasks (id, title, create_date, create_person) VALUES (2, 'walk', sysdate(), 'pangency'); -- テーブルの表示 SELECT * FROM tasks;
コンテナにログインし、上記のsqlファイルを実行してみましょう。
// コンテナ内でディレクトリを移動 # cd home/pangency // MySQLモニターの起動 # mysql -u root -p // 使用するデータベースをpracticeに変更 mysql> use practice; // sqlファイルの読み込み mysql> source create-table.sql; Query OK, 0 rows affected (0.05 sec) Query OK, 0 rows affected (0.09 sec) Query OK, 1 row affected (0.01 sec) Query OK, 1 row affected (0.01 sec) +----+-------------+---------------------+---------------+ | id | title | create_date | create_person | +----+-------------+---------------------+---------------+ | 1 | read a book | 2020-07-20 04:44:34 | pangency | | 2 | walk | 2020-07-20 04:44:34 | pangency | +----+-------------+---------------------+---------------+ 2 rows in set (0.00 sec) // テーブルの確認 mysql> show tables; +--------------------+ | Tables_in_practice | +--------------------+ | tasks | +--------------------+ 1 row in set (0.00 sec)
無事、sqlファイルが読み込まれ、テーブルの作成とデータの挿入ができました!
「この環境なら、実行したいSQLファイルを作成してコマンドラインで即実行できるので色々試せますね!」
まとめ
今回は、Docker Composeを使って、MySQLのDockerコンテナの作成をしてみました。また、ホスト側とコンテナ内でのディレクトリのリンクも行ってみました。
Dockerがあれば、色々な環境を気軽に試せるのでとても便利ですね。
【WSL2】Windows 10 HomeでDocker Desktopを導入する
パンジェン氏「東の森でシステムエンジニアをしております、パンジェンシーと申します。
暑い日が続きますね。テレワークの方はちゃんとエアコンをつけて熱中症に気をつけましょうね!」
なぜ、Docker Desktopなのか
先日、WSL2のUbuntuにDockerをインストールしてみたのですが、WSL2ではsystemctl
というコマンドが使えず、Dockerデーモンの自動起動設定を行うことができませんでした(使えるようにするスクリプトとか作っている人はいるみたいです)。
もう少し調べてみたら、Docker Desktop WSL2 backendというものを発見しました。Docker Desktop for Windowsは、Hyper-Vを使えないWindows 10 Homeでは動かないと思っていましたが、このWSL2 backendという機能を使えば動かせるようです。
これなら、Dockerデーモンの自動起動もできるし、WindowsからもWSL2からもDockerが使えるらしいので、こちらを使うことにしました。
「できるだけ開発絡みのものはWSL2の中に押し込めたかったのですが、自動起動のために複雑な手順が増えるより導入が容易なほうがよいと判断しました…。」
1. 導入済みのDockerを削除
既に過去のエントリーでWSL2内にDockerを導入していたので一旦削除します。やっていない人はこの手順は不要です。
せっかく導入しましたが、色んなバージョンのDockerが入っていると気持ち悪いのでとりあえずアンインストールします。手順は公式ドキュメントの通りです。
$ sudo apt-get purge docker-ce docker-ce-cli containerd.io $ sudo rm -rf /var/lib/docker
2. WSL2を導入
逆に、WSL2の導入が済んでいない人は、以下のエントリー⇩を参考に導入してみてください。
3. Docker Desktopをインストール
https://hub.docker.com/editions/community/docker-ce-desktop-windows/
⇧からインストーラーをダウンロードしてインストールしましょう。「Get Stable」が安定版なのでとりあえずコチラにしましょう。
インストールが終わったら、Windows PowerShellからも、WSL2のターミナルからもdocker -v
をしてみましょう。
まとめ
今回はDocker Desktopを導入してみました。Linux版からDocker Desktopに切り替えてよかったと思える日がいつかきっと多分来るでしょう…。