前回の記事までで、基本的なDockerの使い方と、CaaSの使い方について説明しました。この記事では、「そもそもコンテナって仮想マシンと何が違うんですか」という部分の説明と、前回までで学んだコマンドたちをまとめていきたいと思います。
コンテナと仮想マシンの違い
コンテナと仮想マシンはどちらも仮想化技術の一種です。では何が違うのかというと、仮想化の度合いが違います。
アプリケーションは、基本的には以下のようなレイヤーを通してハードウェアとやり取りし、動作しています。
このレイヤー分けで見たときに、仮想マシンとコンテナを比較すると下図のようになります。
仮想マシンは、仮想マシンの中にOSの全体(システムライブラリとカーネル)を含んでいますが、コンテナの場合はカーネルはホストOSのものを利用し、コンテナの中にはシステムライブラリのみを持ちます。
なにがうれしいのか
仮想マシンに対してコンテナが優れている点はいくつかありますが、その一つとして軽量であるという点が挙げられます。上記の通り、コンテナの場合はカーネルをホストOSのものを使うので、イメージの中に含める必要がありません。そのため、イメージの容量が削減され、仮想マシンのイメージよりも軽量になります。また、仮想マシンのようにハードウェアをエミュレートする必要もないため、動作のオーバーヘッドが少なくなります。こういった理由から、コンテナは容量の点でも、起動の速さの点でも軽量であるといえます。
では、軽量であると何がうれしいのでしょうか。それは、スケーラビリティが高くなるという点です。スケールさせること自体は仮想マシンでも可能ですが、コンテナはその起動の速さから、より柔軟にスケールすることができます。Kubernetesなどのコンテナオーケストレーションツールを用いれば、比較的簡単にスケール管理も行うことができます。
少し注意が必要な点
コンテナは仮想マシンと違って、ホストOSのカーネルを利用するというお話をしました。それゆえに軽量なわけですが、注意すべき点があります。それは、前提とするカーネルが異なるコンテナは動かせないという点です。基本的にはLinuxカーネルを前提とするコンテナを使うことが多いかと思いますが、例えばWindowsのカーネルを前提とするアプリケーションをコンテナにする場合、ホストOSもWindowsのカーネルである必要があります。ですので、「なんでもとりあえずコンテナにしちゃえ!」とはいかないということには注意が必要です。
ここまでのまとめ
最後に、第一回から第四回までで出てきたコマンドなどを整理しておきたいと思います。
Dockerの基本コマンド
コマンド | 説明 |
---|---|
docker container run <image-name> | 新しいコンテナを作成して実行 |
docker container ls | 起動・停止しているコンテナの一覧を確認 |
docker container start <container-name> | 停止しているコンテナを起動 |
docker container stop <container-name> | 起動しているコンテナを停止 |
docker container rm <container-name> | コンテナを削除(停止させてから実行する) |
docker container exec <container-name> <command> | 起動しているコンテナで指定したコマンドを実行 |
docker image build -t <image-name> . | カレントディレクトリのDockerfileからコンテナイメージをビルドする |
docker image ls | コンテナイメージの一覧を確認 |
docker image rm <image-name> | コンテナイメージを削除 |
Dockerfileの基本コマンド
コマンド | 説明 | 使用例 |
---|---|---|
FROM |
ベースとなるイメージを指定します。 | FROM ubuntu:20.04 |
RUN |
イメージのビルド時に実行するコマンドを指定します。 | RUN apt-get update && apt-get install -y nginx |
CMD |
コンテナ起動時に実行するデフォルトのコマンドを指定します。 | CMD ["nginx", "-g", "daemon off;"] |
ENTRYPOINT |
コンテナ起動時に実行するメインのコマンドを指定します。 | ENTRYPOINT ["docker-entrypoint.sh"] |
COPY |
ホストシステムからコンテナにファイルまたはディレクトリをコピーします。 | COPY myapp/ /usr/src/myapp/ |
ADD |
COPY と似ていますが、URLからのダウンロードやアーカイブの自動解凍もサポートします。 |
ADD myapp.tar.gz /usr/src/myapp/ |
ENV |
環境変数を設定します。ビルド時と実行時に使用されます。 | ENV APP_ENV=production |
EXPOSE |
コンテナがリッスンするネットワークポートを指定します。メタデータの一種で、実際に何か操作を行うわけではなく、コンテナがリッスンするポートを分かりやすくしています。 | EXPOSE 80 |
WORKDIR |
作業ディレクトリを設定します。この命令以降の、RUN コマンド等のコマンドが実行されるディレクトリを指定します。 |
WORKDIR /usr/src/myapp |
USER |
コンテナ内でコマンドを実行するユーザーを指定します。 | USER appuser |
VOLUME |
ホストとコンテナ間でマウントされるボリュームを指定します。 | VOLUME /var/lib/mysql |
ARG |
ビルド時に渡される引数を指定します。 | ARG build_env=production |
LABEL |
メタデータをイメージに追加します。バージョン情報やメンテナンス情報を含めるのに便利です。 | LABEL version="1.0" description="A simple example" |
ONBUILD |
このイメージが他のイメージのベースとして使用されたときに実行するコマンドを指定します。 | ONBUILD ADD . /app/src |
カレントディレクトリのDockerfileからビルドしてローカルで動かすまで
docker image build -t <image-name> .
docker run [option] <image-name>
以下は例
$ docker image build -t simple-knowledge-sharing-platform .
$ docker run -d -p 8080:5000 --network flask-net -v $(pwd)/uploads:/app/uploads simple-knowledge-sharing-platform
カレントディレクトリのDockerfileからビルドしてリモートレジストリにプッシュするまで
docker image build -t <image-name> .
docker image ls # ビルドしたイメージを確認
docker tag <ビルドしたイメージ名> <リモートレジストリのレポジトリ名とタグ>
docker push <リモートレジストリのレポジトリ名とタグ>
例は以下
$ docker image build -t simple-knowledge-sharing-platform .
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/simple-knowledge-sharing-platform latest fe705099a994 5 hours ago 238 MB
yyz.ocir.io/orasejapan/simple-knowledge-sharing-platform latest fe705099a994 5 hours ago 238 MB
<none> <none> ff639a5aac72 5 hours ago 238 MB
<none> <none> 7ddb674174a7 4 days ago 238 MB
docker.io/library/mysql 8.0 1eba4c9bcaa8 6 weeks ago 583 MB
docker.io/library/python 3.9-slim 4602238ffbdc 2 months ago 131 MB
$ docker tag localhost/simple-knowledge-sharing-platform:latest yyz.ocir.io/orasejapan/simple-knowledge-sharing-platform:latest
$ docker push yyz.ocir.io/orasejapan/simple-knowledge-sharing-platform:latest
本記事のまとめ
ここまでで、基本的なDockerの使い方については分かったと思います。次回からは、Docker Composeによる複数コンテナの管理について説明していきたいと思います。