この記事はNuco Advent Calendar 2022の22日目の記事です
はじめに
対象読者
この記事では
- Docker初学者の方
- これからDockerを学ぼうとしている方
を対象にやるべきことして以下の3つを紹介します。
- Dockerの全体像を把握する
- チュートリアルで基本操作を学ぶ
- Docker Hubを散策する
自身が初学者だった頃の経験を基になるべく早く効率的にDockerを学ぶためにやるべきことを紹介するので参考にしてもらえれば幸いです。
できるようになること
- Dockerが何なのか理解できるようになります
- Dockerを使ったアプリケーション開発に必要な基礎知識が身につきます
- 記事TOPのクリスマスツリーをターミナルに表示できるようになります
1. Dockerの全体像を把握する
まずはDockerが何者であるかを把握しましょう。実際にコマンドで操作する前にざっくりイメージを膨らませておくことで理解のスピードが上がります。
Dockerはコンテナ型の仮想環境を提供するもの
Dockerは、Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのオープンソースソフトウェアです。
さてコンテナ型の仮想環境とはなんでしょうか?この用語を理解するために仮想環境とコンテナについて説明します。
仮想環境とは
仮想環境の仮想とは疑似的なという意味で使われています。仮想環境はコンピュータの中に疑似的に作った環境のことです。ここでの環境とは開発したり、テストしたり、実際にプログラムを動かしたりするために必要なコンピュータやソフトウェアなどが揃った場所と思ってください。仮想環境を構築することを仮想化といいます。
仮想環境を構築することで、Windows環境の中で仮想的に作られたLinux OS環境を用意したり、Windoiws環境の中にAndroid環境を用意してAndoroidアプリ開発を行ったりすることができます。
コンテナ技術とは
コンテナとは仮想環境を構築する技術の1つです。物流業界で使われるコンテナは中に輸送するものを入れていますが、ここでいうコンテナの場合はアプリケーションが動くのに必要なものがまとまって入っている箱というイメージです。様々な環境においてコンテナで同じ仮想環境を作ることができ、環境ごとの違いによって発生する問題を減らすことができます。
従来の仮想化とコンテナの違い
従来の仮想化はアプリケーションが各々の仮想サーバの中で動作します。アプリケーションを起動するためには物理サーバにインストールされているホストOSとは別に仮想サーバ内でのゲストOSの起動が必要になります。
コンテナによる仮想化では仮想サーバとゲストOSが不要になります。コンテナエンジンがアプリケーションの起動に必要な環境(従来の仮想化のゲストOS)をそれっぽく再現しています。コンテナエンジンがコンテナにゲストOSがあるように見せているとも言えます。そのコンテナエンジンの中で最も有名なのがDockerです。
Dockerを使うメリット
Dockerイメージで簡単に環境構築
初学者にとってはDockerコンテナとDockerイメージの違いがわかりにくいと思います。まずはDockerイメージとはDockerコンテナのテンプレート、DockerコンテナはDockerイメージ(テンプレート)から起動したアプリケーションの動作環境くらいの理解で十分です。
Dockerイメージを共有することで誰でも簡単に同じ環境を用意することができます。
Dockerfileでイメージ構築手順をファイル化できる
DockerfileとはDockerイメージを作成するための手順が記されたテキストファイルです。Dockerイメージの設計図と説明されたりします。仮想環境を構築する手順をテキストで管理できます。
後述する基本コマンドの説明でDockerfileからDockerイメージを作成し、Dockerコンテナを起動するまでの流れを説明します。実際にコマンドを実行してみるとDockerfile、Dockerイメージ、Dockerコンテナそれぞれの役割と関係性が理解できると思います。
軽量で早い
従来の仮想化と異なり、仮想サーバの立ち上げが不要なのでアプリケーションの起動が早いというメリットがあります。これにより開発作業をスムーズに行うことができます。
2. チュートリアルで基本操作を学ぶ
Dockerが何者であるかおおよそのイメージができたら、次はチュートリアルで実際の操作方法を学びます。公式のチュートリアルを終えるとDockerの基本操作はひととおり自信を持って行えるはずです。
また、本章の後半ではチュートリアルの復習も兼ねてよく使うコマンドを紹介するので、ぜひターミナルを開いて操作しながら読み進めてみてください。
やるべきは公式のチュートリアル
Dockerについて調べると、様々なブログや記事が見つかりますが、まずはじめにやるべきは公式のチュートリアルです。
Dockerのインストールが済んでいない方はこちらからインストールしましょう。
こちらのリポジトリに従ってチュートリアルを進めます。
まずはターミナルで次のコマンドを実行します。
$ docker run -d -p 80:80 docker/getting-started
この時点でコマンドの意味はわからなくても大丈夫です。チュートリアルを終える頃には理解できるようになっています。
コマンドを実行すると次のような出力が出てきます。
ブラウザでhttp://localhost/ を開くと次のような画面が開きます。
チュートリアルがとても丁寧に簡単な英語で説明されているので、英語のドキュメントに慣れていない方も頑張って読み進めてほしいです。Dockerを使ったアプリケーション開発をハンズオン形式で学ぶことができます。
和訳している方の記事がありましたので、どうしても英語が無理という方のためにリンクを貼らせていただきます。
Dockerを体系的に学べる公式チュートリアル和訳
まず覚えるべき基本コマンド
チュートリアルでも基本的なコマンドを学べますが、こちらでもおさえておくべきDockerコマンドを紹介します。
コマンドを実行しながら読み進めてみてください。
コンテナ一覧 docker ps
コンテナの一覧を確認するコマンドです。
前述したチュートリアルのコンテナが起動している状態で実行すると次のような出力が確認できます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c064f6d6e88 docker/getting-started "/docker-entrypoint.…" 26 minutes ago Up 26 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp infallible_lewin
イメージ一覧 docker images
イメージの一覧を確認するコマンドです。
前述したチュートリアルのイメージがあると次のような出力が確認できます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker/getting-started latest e5be50c31cd9 12 days ago 29.8 MB
コンテナ停止 docker stop
docker stop <CONTAINER IDまたはNAME>
で起動中のコンテナを停止することができます。
CONTAINER IDが1c064f6d6e88
のコンテナを停止する場合は
$ docker stop 1c064f6d6e88
NAME(ここではinfallible_lewin
)を指定してコンテナを停止する場合は
$ docker stop infallible_lewin
停止したことを確認してみます。docker ps
は起動中のコンテナだけ表示するので、実行すると停止したコンテナは表示されなくなります。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker ps -a
またはdocker ps --all
で停止中のコンテナを含めたすべてのコンテナを表示できます。
STATUSがExitedになっていることからコンテナが停止中であることが確認できます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c064f6d6e88 docker/getting-started "/docker-entrypoint.…" 26 minutes ago Exited (0) 8 minutes ago infallible_lewin
コンテナ起動 docker start
docker start <CONTAINER IDまたはNAME>
でコンテナを起動することができます。
CONTAINER IDが1c064f6d6e88
のコンテナを起動する場合は
$ docker start 1c064f6d6e88
NAME(ここではinfallible_lewin
)を指定してコンテナを起動する場合は次のとおりです。
$ docker start infallible_lewin
イメージ作成 docker build
まず作成するDockerイメージの基となるDockerfileを作成します。
$ cat << EOS > Dockerfile
FROM nginx
EOS
エディターソフトでDockerfileという名前のファイルを作成し、FROM nginx
とだけ入力して作成しても構いません。
Visual Studio Codeで作成するとこんな感じです。
イメージを作成してみます。
$ docker build -t test:qiita .
-t test:qiita
はオプションでDockerイメージに名前とタグをつけています。ここではtestが名前、qiitaがタグです。
最後のピリオド.
はDockerfileのある場所(カレントディレクトリ)を指定しています。
実行すると次のような出力が出てきます。
ここで何が起こっているかというと、DockerfileにFROM
で指定したnginxのイメージをDocker Hubから取得(pullといいます)してローカルPC上にDockerイメージを構築しています。
Docker HubとはDockerイメージを検索・共有するためにDocker社が提供しているサービスです。平たく言うとGitHubのDockerイメージ版です。
docker images
でDockerイメージが作成されていることが確認できます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test qiita 7f7b4ac1ce1f 13 hours ago 142MB
コンテナを起動状態で作成 docker run
作成したDockerイメージからDockerコンテナを作成し、起動してみます。
ここではコンテナを起動した状態で作成するdocker run
を使用します。
$ docker run -d -p 8080:80 --name test-container test
-d
はコンテナをバックグラウンドで動作させるオプションです。
-p 8080:80
はローカルPCのポート8080をコンテナのポート80を結びつけます。
--name test-container
は起動するコンテナにtest-container
という名前をつけています。ここでつけた名前はdockerコマンドでコンテナの指定に使えます。
最後のtest
は基となるDockerイメージの名前です。
docker ps
でDockerコンテナが作成されているか確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09015830f07d test "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp test-container
コンテナの起動が確認できました。
ブラウザでhttp://localhost:8080 を開くと次のような画面が表示されます。docker run
の-p
オプションでローカルPCのポート8080とコンテナのポート80がマッピングされているので、nginxのWebページが表示されます。
80番ポート
インターネットでWeb閲覧をしているとき、ユーザーのPCとサーバと呼ばれるコンピュータが「TCP/IP」と呼ばれるプロトコル群を使って一対一の通信を行なっています。しかし、IPアドレスだけでは利用したいサービスを識別できないため、サーバ側ではアプリケーションプロトコルごとに固定的に割り当てられたポート番号が用意されています。
ポート番号は0から65535まで存在しますが、そのなかでも0~1023までをウェルノウンポート番号といい、IANAという団体により管理されています。TCP/IPにおいて通信で利用されるポート番号のうち、メジャーなサービスやプロトコルが利用するために予約されているポート番号がウェルノウンポート番号です。
80番ポートはHTTPでWebサーバがクライアントサーバと通信する際に利用されます。
コンテナを削除 docker rm
Dockerを使って開発をしていると使わなくなったコンテナを削除することがあります。初心者の場合はコンテナを削除することをためらうかもしれませんので、ここでしっかり削除する流れを学んでおきましょう。
まずdocker ps
でコンテナを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09015830f07d test "/docker-entrypoint.…" 15 minutes ago Up 15 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp test-container
docker stop
でコンテナを停止します。
ここではNAMEを指定して停止します。IDを指定しても構いません。
$ docker stop test-container
docker ps -a
でコンテナの停止を確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09015830f07d test "/docker-entrypoint.…" 16 minutes ago Exited (0) 15 seconds ago test-container
コンテナの停止を確認したら削除してみましょう。
docker rm <CONTAINER IDまたはNAME>
でコンテナを削除することができます。
ここではNAMEを指定して削除します。
$ docker rm test-container
docker ps -a
でコンテナが削除されていることが確認できます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナを停止状態で作成 docker create
再びDockerイメージからDockerコンテナを作成してみます。先程はdocker run
で作成しましたが、ここではdocker create
を使用します。
docker run
とdocker create
はどちらもコンテナを作成するコマンドですが、作成されるコンテナが起動状態か停止状態かという違いがあります。docker run
はコンテナを起動状態で作成し、docker create
はコンテナを停止状態で作成します。
docker run = docker create(コンテナ作成) + docker start(コンテナ起動)
と覚えておきましょう。
実際にコマンドを実行してみます。
$ docker create -p 8080:80 --name test-create test
停止状態でコンテナを作成したのでdocker ps -a
(停止中も含めたすべてのコンテナを表示)で確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5f4e819a872 test "/docker-entrypoint.…" 2 minutes ago Created test-create
docker rm
でコンテナを削除しておきます。ここではCONTAINER IDを指定して削除します。
$ docker rm b5f4e819a872
イメージを削除 docker rmi
docker rmi
はイメージを削除するコマンドです。
まずdocker images
でイメージ一覧を確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test qiita 7f7b4ac1ce1f 13 hours ago 142MB
docker rmi <REPOSITORY:TAGまたはIMAGE ID>
で削除することができます。
ここではREPOSITORY:TAGでイメージを指定して削除してみます。
$ docker rmi test:qiita
最後にdocker images
で削除されていることを確認しましょう。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
使用していないDockerイメージを放置しておくと、いつの間にかディスク容量を圧迫していることになりかねないので、使わないイメージは削除しておきましょう。
イメージを取得 docker pull
DokckerHubからイメージをpull(取得)するコマンドです。Docker Hubにある多くの構築済みのイメージから特定のイメージをダウンロードして使うことができます。
$ docker pull lukaszlach/merry-christmas
例でpullされるイメージlukaszlach/merry-christmas
でコンテナを実行すると記事TOPのクリスマスツリーが現れるので試してみてください。
クリスマスツリーのイメージのDocker Hubはこちら
コンテナ内でコマンド実行 docker exec
docker exec
は起動中のコンテナ内で指定したコマンドを実行します。
いくつか例を試してみます。準備としてexecコマンドを試すためのコンテナを起動します。
$ docker run -d -p 8080:80 --name test-exec nginx
docker ps
で起動を確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc20a5650fe5 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp test-exec
まずはexec
コマンドを使ってコンテナ内でls
コマンドを実行してみます。
$ docker exec test-exec ls -l /usr
test-exec
はコンテナ名、ls -l /usr
がコンテナ内で実行するコマンドです。
以下のようにコンテナ内の/usr
ディレクトリ下のファイル一覧が出力されます。
total 36
drwxr-xr-x 1 root root 4096 Dec 14 01:20 bin
drwxr-xr-x 2 root root 4096 Sep 3 12:10 games
drwxr-xr-x 2 root root 4096 Sep 3 12:10 include
drwxr-xr-x 1 root root 4096 Dec 14 01:20 lib
drwxr-xr-x 3 root root 4096 Sep 24 2020 libexec
drwxr-xr-x 1 root root 4096 Dec 5 00:00 local
drwxr-xr-x 1 root root 4096 Dec 14 01:20 sbin
drwxr-xr-x 1 root root 4096 Dec 14 01:20 share
drwxr-xr-x 2 root root 4096 Sep 3 12:10 src
次はよく利用するコンテナ内でシェルを起動する場合を試してみます。
$ docker exec -it test-exec bash
-it
は-i -t
と同じで-i
は標準入力を開き続けるオプション、-t
は疑似ttyを割り当てるオプションです。
とりあえずは-it
で 手元の環境でdocker内コマンド入力ができるようになると覚えておけばよいでしょう。
コマンドを実行すると以下のようにプロンプトが#
に変わるはずです。このプロンプトはdocker exec
で実行したコンテナ内のbash
が出力しているプロンプトです。
@
のあとの文字列bc20a5650fe5
はコンテナIDです。先程docker ps
で確認したコンテナIDと同じです。
root@bc20a5650fe5:/#
このプロンプトで実行するコマンドはコンテナ内で実行することになります。ls
やcd
など色々なコマンドを実行みてください。
コンテナ内のシェルを終了するときはexit
を実行します。
root@bc20a5650fe5:/# exit
最後にコンテナとイメージを削除しておきます。
docker rm
についている-f
オプションは起動中のコンテナを強制的に削除します。
$ docker rm -f test-exec
$ docker rmi nginx
3. Docker Hubを散策する
やるべきこと3つ目はDocker Hub散策です。様々なイメージのDockerfileを見て勉強しましょう。
Docker Hubとは
前の章でも簡単に触れましたが、Docker HubとはDocker社が運営しているDockerイメージをアップロードして公開・共有できるサービスで、ここで公開されているイメージは自由にダウンロードして使うことができます。公開されているコンテナのベースになっているDockerfileを見ることができるので、Dockerfileの作成に慣れていない方はとても参考になると思います。
Docker Hub
公式イメージのDockerfileを見てみる
試しにpythonの公式イメージを見てみます。Simple Tagsの一番上のリンクを踏んでみます。
GitHubでDockerfileを見ることができます。公式イメージは無駄がなくベストプラクティスにしたがって書かれているので、是非参考にしてみてください。
さらに理解を深めたいあなたへ
Dockerfileのベストプラクティス
最後にDockerfileのベストプラクティスを紹介させていただきます。
保守性が高く軽量で効率的なイメージを作成するためにDocker社が推奨しているものです。
.dockerignoreの使い方やADDとCOPYの違いなどを学ぶことができます。公式チュートリアルを終えたあとはこちらを学ぶことでより実践的な力が身につくでしょう。
おわりに
最後まで読んでいただきありがとうございます。
弊社では、経験の有無を問わず、社員やインターン生の採用を行っています。
興味のある方はこちらをご覧ください。