この記事は Docker Advent Calendar 2019 2日目の記事です。
昨日は @kai_kou さんによる AWSとGCPのインスタンスやコンテナサービスをDockerコンテナ上のUnixBenchでベンチマークして比較してみた でした。
初学者向けDockerfileハンズオン
Docker初学者向けにDockerfileハンズオンを実施しましたので、その時に作ったハンズオン資料を公開します。
DockerコマンドおよびDockerfileに慣れることが目的のハンズオンの資料ですので、Dockerの詳しい説明はしません。
また、お使いのPCにDockerはインストール済みという前提で進めます。
文章の手順通りに進めていけば、DockerコマンドとDockerfileの体験ができます!
軽量なLinux・・・それがalpine
Linuxといえば、CentOSやUbuntuが有名ですが、Docker界隈では軽量なalpineを使うのが定番です。
以後、alpineを使う前提で話を進めます。
Windows/Mac上で動くalpineマシンがほしい!
なぜDockerを使うのか? WindowsやMac上でLinuxを使いたいからです!
ここからはWindows/Mac上でalpineを使う体験をしていきたいと思います。
alpine入りのDockerイメージをpullする
まずは、Dockerイメージというものを入手しましょう。Dockerイメージというのは、Linuxマシンのひな型だと思ってください。
Docker Hub にDockerイメージが公開されていますので、それを以下のコマンドでダウンロードします。
# alpineのDockerイメージをダウンロードする
docker pull alpine:3.9
もしネットワークがプロキシ配下にある場合、ここでエラーが発生するかもしれません!
Dockerのプロキシの設定を確認してみてください。
alpine入りのDockerコンテナを生成する
次にDockerコンテナを生成します。Dockerコンテナというのは、Linuxマシン本体のことだと思ってください。
以下のコマンドで、コンテナを生成し、そのコンテナに入ります。
# Dockerコンテナを生成して入る
docker run -it alpine:3.9 /bin/ash
これだけで、alpineマシンに入ることができます!
docker run
というのはコンテナを起動するというコマンドです。
-i
は標準入力を受け付けるというオプションです。
-t
は疑似TTYを割り当てるというオプションで、 -it
のようにくっつけることで、コンテナ内に入力ができるようになります。
コンテナに対し入力できる状態のことを コンテナに入る と本記事では呼ぶことにします。
bin/ash
というのは、コンテナ内で使用するシェルが bin/ash
であるという意味です。alpineでは bin/bash
が使えないので、代わりに /bin/ash
を使います。 (なので、タイプミスではありませんw)
コンテナに入れたら、 exit
で抜けましょう。
# コンテナから抜ける
exit
作成したコンテナのIDを確認する
exit
で抜けましたが、コンテナは消えたわけではなく、まだ存在しています。
以下のコマンドでIDを確認してみましょう!
# 作成したDockerコンテナを確認する
docker ps -af ancestor=alpine:3.9
以下のような情報が表示がされます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0cf65c560abb alpine:3.9 "/bin/ash" 4 minutes ago Exited (0) 4 minutes ago vigilant_knuth
docker ps
というのは、Dockerコンテナの一覧を表示するコマンドです。
-a
は停止中のものも含めてすべてのコンテナを表示する候補にするというオプションです。
-f ancestor=alpine:3.9
は、候補のうち、イメージ名が alpine:3.9
のものを表示するという意味です。
-a
と -f
は -af
のようにくっつけることができます。
もう一度起動してコンテナのIDを確認する
もう一度コンテナを起動します。
# Dockerコンテナを生成して入る
docker run -it alpine:3.9 /bin/ash
コンテナに入れたら、すぐに抜けます。
# コンテナから抜ける
exit
再び、コンテナのIDを確認しましょう。
# 作成したDockerコンテナを確認する
docker ps -af ancestor=alpine:3.9
今度は以下のように表示されます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a4a95f438cbc alpine:3.9 "/bin/ash" 12 seconds ago Exited (0) 2 seconds ago serene_dubinsky
0cf65c560abb alpine:3.9 "/bin/ash" 4 minutes ago Exited (0) 4 minutes ago vigilant_knuth
あれ? 2つに増えてる??
はい、そうなんです。実は、 docker run
する度に、以下のように新しいコンテナが生成されるんです。
先ほど、コンテナはLinuxマシンに相当すると説明しました。
現在のこの状況は、つまりLinuxマシンが2台あるということになります。
私が初めてこの docker run
コマンドを触ったときは、「Linuxマシンを2台も作るなんて贅沢だ!1台を使いまわせばいいじゃないか」 と思いました。
しかし、Docker界隈には、 1つのコンテナを使いまわさずに、毎回新品のコンテナを使おう! という考え方があるんです。
1つのコンテナを使いまわすと、メモリエラー等が累積していき、徐々に動きがおかしくなっていきます。
毎回、まっさらなコンテナを用意することで、そういったリスクを回避することができるんです。
作成したコンテナを削除する
今度は作成したコンテナを削除してみましょう。
以下のようにコンテナIDを指定してコンテナを削除してください。
# Dockerコンテナを削除する
docker rm a4a95f438cbc
docker rm 0cf65c560abb
# 作成したDockerコンテナを確認する
docker ps -af ancestor=alpine:3.9
綺麗になくなりました!
Node.jsを使いたい
次に、Node.jsが入ったDockerイメージを入手しましょう。
Node.js入りのDockerイメージを入手して起動する
Node.js入りのDockerイメージが公開されていますのでプルします。
# Node.js入りのDockerイメージをダウンロードする
docker pull node:12.3.1-alpine
# Dockerコンテナを生成して入る
docker run -it node:12.3.1-alpine /bin/ash
コンテナに入れたら、Node.jsがインストールされているか確認してみましょう。
# Node.jsのバージョンを確認する
node --version
v12.3.1
今度はNode.jsが入ってました!
exit
で抜けましょう。
# コンテナから抜ける
exit
Dockerコンテナを一括削除したい
先ほどは、コンテナIDを指定してコンテナを削除しました。ただ、毎回コンテナIDを手作業で調べるのはかなり面倒です。
これから説明するコマンドを使えば、停止用のコンテナを一括して削除することができます。
ただし、 利用には細心の注意が必要です。
データベースやログ等、大事なデータが格納されているコンテナ等が停止していた場合、そのデータ毎コンテナが消えてしまいます。
それを理解した上で、停止中のコンテナを一括で削除したい場合は、以下のコマンドを実行してください。
# 停止中のコンテナを一括削除する
docker container prune
「コンテナを使いまわさない」というルールで運用しているのであれば、上記のコマンドを叩いても基本的には問題はおこらないはずですが、念のため、注意を記載させていただきました。
Dockerコンテナ内にフォルダを作りたい
コンテナ内に /src/app
というフォルダを作成したいとします。
まずは、ダメなやり方から紹介します。
# Dockerコンテナを生成して入る
docker run -it node:12.3.1-alpine /bin/ash
上記のようにコンテナを生成してから、以下のようにLinuxコマンドでフォルダを作成します。
# /src フォルダを作成する
mkdir /src
# /src/app フォルダを作成する
mkdir /src/app
# 終了
exit
このようにフォルダを作成したコンテナを閉じた場合、次にコンテナを生成した時に、同じフォルダはあるのでしょうか?もう一度、Dockerコンテナを生成しフォルダがあるか確認します。
# Dockerコンテナを生成して入る
docker run -it node:12.3.1-alpine /bin/ash
コンテナに入れたら、フォルダがあるか確認します。
# フォルダがあるか確認する
ls -al /src/app
ls: /src/app: No such file or directory
エラーが発生しました! 作成したはずのフォルダがありません!
何度も言いますが、 docker run
する度に、新しいコンテナが生成されるので、前のコンテナの状態は引き継がれないのです。
毎回新品のコンテナを使うという考え方は理解できますけど、状態が引き継げないのは不便ですよね。
フォルダ作成済みのDockerイメージを作りたい
実は、 Dockerfile
という仕組みを使えば、フォルダが作成済みの状態のDockerイメージを作ることができるんです。
作業ディレクトリを作る
まずは、 Dockerfile
を置くためのディレクトリを作ります。
とりあえず、今回は
- Windows:
D:\Docker\DockerHandson
- Mac:
~/Docker/DockerHandson
とします。上記に限らず、お好きな場所で結構です。
このディレクトリを以後、 作業ディレクトリ
と呼ぶことにします。
Dockerfileを書いてみる
作業ディレクトリに Dockerfile
という名前のファイルを作成します。拡張子はありません。
# Node.js
FROM node:12.3.1-alpine
# フォルダ作成&移動
WORKDIR /src/app
FROM
は、ベースにするDockerイメージを指定するコマンドです。
WORKDIR
は、Dockerイメージ内にフォルダを作成し、かつ、カレントディレクトリをそのフォルダにするコマンドです。
Dockerイメージを作ってみる
カレントディレクトリを作業ディレクトリにした状態で、以下のコマンドを叩きます。
# DockerfileをもとにDockerイメージを作成する
docker build -t hoge:0.1.0 ./
すると、 hoge:0.1.0
という名前のDockerイメージが生成されます。
docker build
というのは、 Dockerfile
をもとにDockerイメージを生成するコマンドです。
-t hoge:0.1.0
は、作成するイメージに hoge:0.1.0
という名前を付けています。
最後の ./
は Dockerfile
が設置されているディレクトリへの相対パスです。
これで、 hoge:0.1.0
が生成されます。
本当に生成されたのでしょうか?以下のコマンドで確認しましょう。
# hoge
docker images hoge
以下のように表示されます。
REPOSITORY TAG IMAGE ID CREATED
SIZE
hoge 0.1.0 3e9a3b5598db 12 seconds ago
79.6MB
Dockerイメージが作成されていますね!
Dockerコンテナに入ってみる
作成した hoge:0.1.0
のコンテナを生成して入ってみます。
# 作ったDockerイメージからDockerコンテナを生成して入る
docker run -it hoge:0.1.0 /bin/ash
フォルダがあるか確認します。
# フォルダがあるか確認する
ls -al /src/app
以下のように表示されると思います。
total 8
drwxr-xr-x 2 root root 4096 Nov 12 10:26 .
drwxr-xr-x 3 root root 4096 Nov 12 10:26 ..
今度はフォルダがありました!
今後は、このイメージを元にコンテナを作成すれば、フォルダが作成済みの状態で作業ができそうです。
ホスト(Win/Mac)のファイル群をDockerイメージにコピーしたい
ここまでは、フォルダ作成済みのDockerイメージを作りました。
次は、そのフォルダにホスト(Windows/Mac)側のファイルをコピーしたDockerイメージを作ってみます。
ホスト側にappフォルダを作る
作業ディレクトリ直下にappフォルダを作り、その中に index.html
を作りましょう。
index.html
の中身はこんな感じです。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>タイトル</title>
</head>
<body>
本文
</body>
</html>
Dockerfileを改良する
作業ディレクトリ直下の Dockerfile
を以下のように書き換えます。
# Node.js
FROM node:12.3.1-alpine
# フォルダ作成&移動
WORKDIR /src/app
# 必要なファイルをコピー
COPY ./app /src/app
COPY
というコマンドが登場しました。これはホスト(Windows/Mac)側にある ./app
というフォルダの中身を、Dockerイメージ側の /src/app
にコピーするという意味になります。
この Dockerfile
をもとにDockerイメージを作成しましょう。今度はタグを 0.2.0
にしてます。
# DockerfileをもとにDockerイメージを作成する
docker build -t hoge:0.2.0 ./
これで hoge:0.2.0
というDockerイメージが作成されました。
Dockerコンテナを確認する
いつも通りにDockerコンテナを生成してみます。
# 作ったDockerイメージからDockerコンテナを生成して入る
docker run -it hoge:0.2.0 /bin/ash
Dockerコンテナ内に index.html
があるか確認してみましょう!
# ファイルがあるか確認する
cat /src/app/index.html
HTMLの中身が表示されると思います!
Dockerコンテナ内のHTMLをホスト側のブラウザから見れないの?
せっかくHTMLファイルを置いたので、今度はホスト側のブラウザからHTMLファイルを閲覧する方法を考えます。
以下の作業をすればできます。
- ポートを開放する
- Expressをインストールする
Expressの導入は、長くなってしまいますので、今回は省略することにしました。申し訳ありません。
さいごに
Dockerfile
を触ってみていかがでしたでしょうか?
実際に手を動かしてみることで、Dockerの雰囲気が何となくわかったかなと思います。
最後に、いらなくなったコンテナを削除しましょう!
# 未使用コンテナを一括削除する
docker container prune
以上、おつかれさまでした。
この記事は Docker Advent Calendar 2019 2日目の記事でした。
明日は @ProjectEuropa さんによる PHPやRubyとNode.jsを同一コンテナ内に手っ取り早く管理したい人のためのマルチステージビルド です。