いろいろ書いていく

やってみたなど

Docker Compose で WordPress

web+dbなど, 複数のコンテナやサービスで構成されるアプリを構築する際の手段の一つにDocker Composeがある.
構成パラメータをymlに書き出すので, ymlを読むと何をしているのかが何となくわかるのがいい感じ.
今回はお試しWordPress環境の構築を例に, Docker Composeを使ってみる.
(DockerHubに書いてあることをほぼそのままやる. )
https://hub.docker.com/_/wordpress

環境

$ docker -v
Docker version 18.09.0, build 4d60db4
  • docker-composeのインストール

Linux環境でDockerをインストールしていても, Docker Composeはインストールされない.
以下を参考にホストマシンにdocker-composeをインストールする.
docs.docker.com

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617    0   617    0     0    864      0 --:--:-- --:--:-- --:--:--   862
100 11.1M  100 11.1M    0     0   783k      0  0:00:14  0:00:14 --:--:-- 1098k
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.23.1, build b02f1306
$ 
  • Docker Composeをインストールしたら, 適当なディレクトリで以下のstack.ymlファイルを作成
version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'

最新のWordPressMySQL 5.7のイメージを指定している.
WORDPRESS_DB_ で接続先のデータベースの情報を指定する.

$ docker-compose -f stack.yml up

(略)

-fオプションはupの前にしないとエラーが出るかも.
このコマンドにより, ymlで指定したイメージの取得, WordPressコンテナとMySQLコンテナの起動, db接続などが行われる.
dbの互換性などでうまく起動しない場合もあるので, その場合はdbのバージョンを変更して試してみる.
Docker内でのネットワークもデフォルト設定で作成してくれる.
作成されたネットワークの情報はdocker network inspectで確認できる

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
df9f685f5ba9        bridge              bridge              local
6dc567989d6f        host                host                local
dd596238709d        none                null                local
0e8b407e4748        wordpress_default   bridge              local

$ docker network inspect wordpress_default 
[
    {
        "Name": "wordpress_default",
        "Id": "0e8b407e474893dccf87901d5430d012e0d6e9900ea624cdb08a76bed14a2688",
        "Created": "2019-01-01T13:14:04.278596181+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9b60a44e3db6693a605a9a8328e4ec78bfff8031b4f85c22e95f1e825c12c10d": {
                "Name": "wordpress_wordpress_1_c757a4d508cd",
                "EndpointID": "a1c750990e9f00868321ea9ad38d007ede2924f10719ae0b93d4f19362cd14fe",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "ea3572652f4ab07568d530e3cb11b816a5cae7144d232888e293bd0cca6fd932": {
                "Name": "wordpress_db_1_3c36a9263ab8",
                "EndpointID": "47154ceb96f3695878d364e4f2075e146f272919264855d7631b9854894c311d",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "wordpress",
            "com.docker.compose.version": "1.23.1"
        }
    }
]
  • こんな感じの仮想ネットワークが作成されている.

f:id:koimedenshi:20190101144944p:plain

  • 各コンテナのステータスやポートはdocker-compose psで確認できる.
$ docker-compose -f stack.yml ps
         Name                                                                     Command           State          Ports        
--------------------------------------------------------------------------------------------------
wordpress_db_1_3c36a9263ab8               docker-entrypoint.sh mysqld       Up      3306/tcp, 33060/tcp 
wordpress_wordpress_1_c757a4d508cd   docker-entrypoint.sh apach ...     Up      0.0.0.0:8080->80/tcp
  • docker-composeがうまくいったら, ブラウザを開いてhttp://localhost:8080 にアクセスすると初期設定画面が開く

f:id:koimedenshi:20190101013406p:plain

設定を順次行い, ブログ作成などをやってみる.

おわり.

$ docker-compose -f stack.yml down --rmi all

--rmiオプションでallを指定すると, docker-composeで作成したコンテナ・イメージ・ネットワークなどが一括削除される.

以上

Docker Tomcatにsample.warをデプロイする Dockerfile編

前回の記事ではTomcatコンテナに入ってサンプルアプリをデプロイしてみた.
koimedenshi.hatenablog.com

今回は同じことをDockerfileでやってみる.

環境

$ docker -v
Docker version 18.09.0, build 4d60db4

前回同様サンプルアプリ(sample.war)をCATALINA_BASEにデプロイするが, コンテナに入り込むのではなく, アプリがデプロイされたイメージからコンテナを起動する.

まず以下の内容でDockerfileを作成する.

FROM tomcat:8.5.37

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
WORKDIR $CATALINA_HOME

RUN set -ex; \
	cd webapps && \
	wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war 

わりとシンプルだと思うが, ざっくり言うと「tomcat:8.5.37のイメージを用意して, CATALINA_HOME/webappsにsample.warをダウンロードしてね」という指示を書いている.
詳しいことはググってください(ひどい)
tomcat:8.5.37は現時点でのlatestを選択した.

このファイルを保存したディレクトリでdocker buildする.

$ docker build . -t sample:0.1
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM tomcat:8.5.37
 ---> ef802ca71927
Step 2/5 : ENV CATALINA_HOME /usr/local/tomcat
 ---> Running in 96bc5a455775
Removing intermediate container 96bc5a455775
 ---> 21a687433aee
Step 3/5 : ENV PATH $CATALINA_HOME/bin:$PATH
 ---> Running in 1d2b1a0510fa
Removing intermediate container 1d2b1a0510fa
 ---> 09499132613c
Step 4/5 : WORKDIR $CATALINA_HOME
 ---> Running in e187f9a604f5
Removing intermediate container e187f9a604f5
 ---> 27b0a898e31c
Step 5/5 : RUN set -ex; 	cd webapps && 	wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war
 ---> Running in 24ec52d55e3c
+ cd webapps
+ wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war

(略)

Successfully tagged sample:0.1
$ 

イメージ作成に成功したら, 作成したイメージを用いてコンテナを起動する.

$ docker container run --name sample-container -p 80:8080 sample:0.1

(略)

コンテナが起動したら, ブラウザからhttp://localhost/sampleにアクセスしてJSP Pageやservletが正常に開けることを確認.

おわり.

不要なコンテナやイメージは削除.

$ docker container stop sample-container
sample-container
$ docker container rm sample-container 
sample-container
$ docker image rm sample:0.1

(略)

公式のDockerfileを引用したので, たぶん余計なコマンドが入っていてすみません.
warファイル取得方法はADDを使うとか, これ以外にもいろいろな方法があると思う.

Docker Tomcatにsample.warをデプロイする

これまでの記事で, DockerでApache Tomcatコンテナを構築する方法を2通りやってみた.
DockerでTomcatその1 - いろいろ書いていくつもり
DockerでTomcatその2 ( docker build ) - いろいろ書いていくつもり

といってもコンテナを起動しただけで味気ないので, 今回はサンプルアプリをデプロイしてみる.

環境

$ docker -v
Docker version 18.09.0, build 4d60db4

アプリのデプロイ手順

Tomcat公式で公開されているサンプルアプリ(sample.war)を, TomcatコンテナのCATALINA_BASE/webappsに保存するだけ.
http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/

warファイルを保存すると, 自動的にアプリがデプロイされる.
CATALINA_BASEは環境によって異なるが, Docker公式イメージではCATALINA_BASE=/usr/local/tomcat/ となる(Docker Hubに書いてある).
https://hub.docker.com/_/tomcat/

warファイルの保存方法はいろいろ考えられるが, 今回はコンテナに入り込んで手動で行う.
ほかの方法は次以降の記事で書く, かも.

手順

1. tomcat container起動
以下のコマンドによりTomcatコンテナを起動.

$ docker container run --name tomcat-example -p 80:8080 tomcat:8.5.35
(略)
XX-Dec-2018 XX:XX:XX.XXX INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1639 ms

イメージがローカルに保存されていない場合, イメージのダウンロードも同時に行われる.

2. コンテナ内でbashプロセスを起動し, ダウンロード
ターミナルをもうひとつ開いて, docker execコマンドでコンテナ内でbashを起動

$ docker exec -it tomcat-example /bin/bash
root@d37eaefd6537:/usr/local/tomcat#

3. /usr/local/tomcat/webappsに移動し, warファイルをダウンロードする

root@d37eaefd6537:/usr/local/tomcat# cd webapps
root@d37eaefd6537:/usr/local/tomcat/webapps# wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war
Saving to: ‘sample.war’

sample.war          100%[===================>]   4.50K  --.-KB/s    in 0s      

2018-12-XX (380 MB/s) - ‘sample.war’ saved [4606/4606]

4. ブラウザで動作確認
ブラウザでhttp://localhost/sampleにアクセス.
JSP pageやServletへのリンクをクリックして, 正常に動作することを確認.

5. おわり
不要なコンテナやイメージは削除.

$ docker container stop tomcat-example
tomcat-example
$ docker container rm tomcat-example 
tomcat-example
$ docker image rm tomcat:8.5.35
Untagged: tomcat:8.5.35
(略)

こういう手動操作があるような場合は, コンテナにbashwgetをインストールしてあると楽ですね.

DockerでTomcatその2 ( docker build )

前回の記事で,docker image pullで公式イメージを取ってくる手順を書いた
DockerでTomcatその1 - いろいろ書いていくつもり

今回はdocker buildを使ってみる.
公式のコードそのままではうまくいかないことがあったので,その辺りも書く.

環境

コンテナで立てるアプリはApache Tomcat.
Apache Tomcat - Wikipedia

公式イメージの使用可能なバージョン等はDocker Hubで確認できる
https://hub.docker.com/_/tomcat/
今回は執筆時点におけるlatestバージョンである8.5.35を用いる.

手順

  • Docker HubのDockerfileリンクを辿って,8.5.35のDockerfileをダウンロードする

https://hub.docker.com/_/tomcat/

github.com

  • ファイル名は"Dockerfile"のままにする.(変更してもよいが,その場合は後のbuildコマンドで-fオプションで指定する)
  • Dockerfileのあるディレクトリでターミナルを開く
  • ここでdocker buildすればイメージ完成..のはずなのだが,このままだとうまくいかなかった.
$ docker build -t tomcat:8.5.35 .
 (sniped)
...returned a non-zero code: 2
  • -tオプションによりTAG名"tomcat:8.5.35"でイメージ作成しているが,リストにも中間生成物的なものしか見当たらない
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
<none>              <none>              b334452e1e39        About a minute ago   447MB
openjdk             8-jre               dd20fb277e3c        3 weeks ago          443MB
  • 実行時のエラーを追ってみると,gpg鍵の検索に失敗した後終了しているっぽい
(sniped)
+ mktemp -d
+ export GNUPGHOME=/tmp/tmp.QmRGq0ytuG
+ gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys XXXXXXXX
gpg: keybox '/tmp/tmp.QmRGq0ytuG/pubring.kbx' created
gpg: keyserver receive failed: Cannot assign requested address
(sniped)

最後のエラー文で検索すると,同じような現象が多数報告されている
Key server down for get.docker.com · Issue #13555 · moby/moby · GitHub

keyserverをpgp.mit.edu や keyserver.ubuntu.comにしてみろとのこと

  • Dockerfileのkeyserverの値を上記のいずれかに変更して保存
                gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \

↓↓↓

                gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
  • 再度buildする前に,中間生成物的なものを削除する(しなくてもよいが,あとでゴミが残るので・・・詳しくは後ほど)
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              b334452e1e39        36 minutes ago      447MB
  • IMAGE ID指定で削除しようとすると,停止中のコンテナで使っていると怒られる
$ docker image rm b334452e1e39
Error response from daemon: conflict: unable to delete b334452e1e39 (must be forced) - image is being used by stopped container 2642a25811d8
  • 中間生成物として作られた不要なコンテナなので,削除する
$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
2642a25811d8        b334452e1e39        "/bin/sh -c 'set -eu…"   36 minutes ago      Exited (2) 36 minutes ago                       objective_engelbart

$ docker container rm 2642a25811d8
2642a25811d8

$ docker image rm b334452e1e39
Deleted: sha256:b334452 ...
 (sniped)

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
  • 綺麗にしたところで,もう一度buildコマンドを実行
$ docker build -t tomcat:8.5.35 .
 (sniped)
Successfully built 5734bc644c71
Successfully tagged tomcat:8.5.35
  • 成功すると指定したタグのイメージが一覧に追加される.
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
tomcat              8.5.35              5734bc644c71        About a minute ago   475MB
openjdk             8-jre               dd20fb277e3c        4 weeks ago          443MB
  • 同じエラーが出た場合は,他のkey serverを試してみるか,コメントアウトするしかない・・・
  • 前回同様,追加されたイメージを用いてコンテナを起動する
$ docker container run -p 80:8080 --name my-tomcat-2 tomcat:8.5.35
 (snip)
XX-Dec-2018 XX:XX:XX.XXX INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2327 ms
  • コンテナ一覧でも見えるはず
$ docker container ls
  • 最後にブラウザでhttp://localhost/にアクセスし, Tomcat/8.3.35のトップページが表示されることを確認

http://localhost/examples/にあるJavaアプリも動くはず

  • 終わり.
  • コンテナとイメージを(目的は果たしたので)削除
# コンテナ停止
$ docker container stop my-tomcat-2
# コンテナ削除
$ docker container rm my-tomcat-2
$ docker container ls
# イメージ削除
$ docker image rm tomcat:8.5.35
$ docker image ls
  • 他の公式Dockerfileでも上記のkey serverをつかっているのが見受けられたので,同じような現象が起きるかも.

余談

  • docker buildコマンドはDockerfileのRUNなどの処理を1行ずつ実行し,その度に中間イメージおよびコンテナを生成している
  • そのため,上記手順の中で中間生成物を削除しないで継続すると,エラーで落ちたところから再開してくれるので少し速くなる.
  • 楽でいいかなと思ったが,後でイメージを削除する際に中間生成物が残っており,ちょっと微妙だったので先に削除した.

DockerでTomcatその1

Docker imageを準備するにはいくつかの方法がある.

  • docker image pull
  • docker build
  • docker import

などなど

今回はdocker image pullで公式イメージを落として,コンテナを起動するところまでをやってみる.

環境

コンテナで立てるアプリはApache Tomcat.
Apache Tomcat - Wikipedia

公式イメージの使用可能なバージョン等はDocker Hubで確認できる
https://hub.docker.com/_/tomcat/
今回は執筆時点におけるlatestバージョンである8.5.35を用いる.

手順

  • Docker Tomcat公式イメージをバージョン指定(8.5.35)で取得
$ docker image pull tomcat:8.5.35
8.5.35: Pulling from library/tomcat
54f7e8ac135a: Pull complete 
d6341e30912f: Pull complete 
 (sniped)
d1786b40ed4f: Pull complete 
Digest: sha256:d6f67aacce64010880a1e9ea6f0ace9fe9e20d39aae0489c8e88b4c14effe3a0
Status: Downloaded newer image for tomcat:8.5.35
  • 成功するとイメージ一覧に追加される.
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              8.5.35              48dd385504b1        5 days ago          475MB
  • 追加されたイメージを用いてコンテナを起動する
$ docker container run -p 80:8080 --name my-tomcat-1 tomcat:8.5.35
 (snip)
XX-Dec-2018 15:00:37.407 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2327 ms

(なお,今回は先にイメージ取得を行なったが,docker container runすると足りないイメージも取得してくれるので,イメージ取得は省略できる.
いきなりdocker container run..をしても同じ結果となる.)

  • 新たにターミナルを開いて以下のコマンドを実行し, コンテナが起動していることを確認
$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
82b62a5f6b31        tomcat:8.5.35       "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:80->8080/tcp   my-tomcat-1
  • コンテナとイメージを(目的は果たしたので)削除
# コンテナ停止
$ docker container stop my-tomcat-1
# コンテナ削除
$ docker container rm my-tomcat-1
$ docker container ls
# イメージ削除
$ docker image rm tomcat:8.5.35
$ docker image ls

以上

Docker daemon attack surfaceを読んだ

Dockerの公式ドキュメントにセキュリティ関連のページがある.
docs.docker.com

Dockerの仕様と,それに起因するセキュリティ上の注意事項がまとめてある感じ.
今回はそのなかのひとつ"Docker daemon attack surface"を読んでわかったことをまとめてみる.
(これから勉強しようという人が書いているので,かなり初歩的だし,ミスリードがあるかもしれない.間違ってたらごめんなさい.)

ここに書いてあることが常に正しいかどうかはわからない.
設定や使用環境によっては気にしないでよいこともあるかもしれない.
それでも基本的な考え方として知っておくことは無駄ではなさそう.

ポイント

とにもかくにも,信頼されたユーザだけがDocker daemonを操作できるようにすること
Docker daemonとはDockerの機能を実現するdaemonのことで,dockerコマンドの宛先といったところ.
操作コマンドの使用を制限するのは当たり前のことにも思えるが,なぜ大事なのか.

もう少し詳しく

Dockerコンテナはホストとディレクトリを制限なく共有する仕様となっている.
設定次第では,コンテナからホスト側のファイルシステムにアクセスすることも可能となりうる.

例えば外部から任意のコンテナを構築可能なサーバを立ててしまうと,悪意のあるユーザにコンテナの外のホストごとやられ放題となってしまう.
三者によってC2サーバに使われてしまったり,ボットネットに組み込まれてしまうかもしれない.

そのようなリスクを踏まえ,Docker CLIREST APIはバージョン0.5.2以降はUNIXソケットを使う仕様になっている.
Docker Engine release notes | Docker Documentation

0.5.2 (2013-08-08)

Builder: Forbid certain paths within docker build ADD
Runtime: Change network range to avoid conflict with EC2 DNS
API: Change daemon to listen on unix socket by default


それまでのTCPソケットによる待ち受けに比べ,従来のUNIX権限チェックを適用することでサーバを守れるため,リスクを減らせるという判断だ.

現在でも設定変更によってREST APIをHTTP経由で叩くことも可能だが,その場合はVPNを張ったり,HTTPSを使うなどでAPI向けの通信を保護したほうがよい.

これ以外にもDockerデーモンは,docker loadやdocker pullなどのイメージ読み込みに対しても脆弱である.
開発者が知らないうちに悪性なイメージを使っていて,それをリリースしてしまう,ということがあるかもしれない.
これに対してはまずバージョン1.3.2でサンドボックス上に展開するような仕様に変更され,さらに1.10.0(下記リンク)からはdocker imageをチェックサムで管理するようにすることで,正規のイメージを保護している.
blog.docker.com
使用しているイメージが意図したものであるかどうかは,IDを見ればよい.

最後に,Dockerを公開する場合は他のサービスと混在させないようにしつつ,必要なサービスはすべてコンテナでまかなうとよい.
(もちろんsshやログ保存系などの管理ツールは入れてもいい,と書いてある.)

終わりに

Dockerセキュリティのうち,docker daemonの攻撃ベクトルについて読んだ.
実運用では面倒だからTCPポートを晒してしまうこともあるだろうし,イメージのチェックサムをいちいち確認しないようなこともあるかもしれない.
それでも,それによって被るリスクを知っておくことは大事だと思う.
このドキュメントにはdaemon以外のセキュリティについても書かれているので,そのうち読んでみたい.
もちろん今はコンテナ管理を便利にするツールがたくさんあるはず(dockerコマンドだけで実運用する人は少なそう)なので,その辺も追々使ってみたい.

Ubuntu18.04にDockerをインストールする

VirtualBox VMUbuntu 18.04にDocker CEをインストールする.

環境

インストールするもの

  • Docker CE stable (version 18.09.0)

手順

  • 先にインストール済みのDockerをアンインストールしたい場合、以下コマンドを実行.(初めてインストールする場合は不要)
 $ sudo apt-get remove docker docker-engine docker.io
  • aptインストールの際にHTTPS通信するためのパッケージをインストール.
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  • DockerのPGP鍵を追加し, apt-keyが "9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88" であることを確認.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
      (snip)
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
  • Dockerのレポジトリを追加.
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
  • Dockerをインストール.
$ sudo apt-get update
$ sudo apt-get install docker-ce
  • dockerコマンドでHello-Worldコンテナを実行し、成功メッセージが出ればインストール完了.
$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
(snip)

dockerコマンド実行時のsudoを不要にする方法(任意)

 Docker daemonUnix socketにバインドされ, 通常rootでしかアクセスできない.
root以外のユーザでsudoせずにdockerコマンドを実行するためには, そのユーザをdockerグループに追加する手順が必要.
セキュリティ上の観点から, 信頼されたユーザのみを追加すること.
詳細はDocker security | Docker Documentationを参照のこと.

  • dockerグループを作成
$ sudo groupadd docker

※インストール後に実施すると「既にある」と怒られるので、同時に作成されているかも

  • dockerグループにユーザを追加
$ sudo usermod -aG docker <追加したいユーザ名>
  • VMから一度ログアウトして再度ログインするか, VMを再起動して, 以下コマンドが成功すればOK.
$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
(snip)

うまくいかないときは, 公式ドキュメントの対応方法などを確認:
Post-installation steps for Linux | Docker Documentation

Dockerをシステム起動時に自動起動させない方法(任意)

ふつうにインストールすると, Dockerがシステム起動と同時に起動する設定となっている.
これをオフにするためには, 以下のコマンドを実行する.

$ sudo systemctl disable docker

以上.