LoginSignup
42
41

More than 3 years have passed since last update.

初学者向けDockerfileハンズオン

Last updated at Posted at 2019-12-01

この記事は 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する

image.png

まずは、Dockerイメージというものを入手しましょう。Dockerイメージというのは、Linuxマシンのひな型だと思ってください。

Docker Hub にDockerイメージが公開されていますので、それを以下のコマンドでダウンロードします。

# alpineのDockerイメージをダウンロードする
docker pull alpine:3.9

もしネットワークがプロキシ配下にある場合、ここでエラーが発生するかもしれません!

Dockerのプロキシの設定を確認してみてください。

alpine入りのDockerコンテナを生成する

image.png

次に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を確認する

image.png

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 する度に、以下のように新しいコンテナが生成されるんです。

image.png

先ほど、コンテナは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イメージを入手して起動する

image.png

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 という名前のファイルを作成します。拡張子はありません。

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 を作りましょう。

image.png

index.html の中身はこんな感じです。

index.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>タイトル</title>
</head>

<body>
    本文
</body>

</html>

Dockerfileを改良する

作業ディレクトリ直下の 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を同一コンテナ内に手っ取り早く管理したい人のためのマルチステージビルド です。

42
41
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
41