takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

VirtualBox + Vagrant で構築した Docker 環境で動作している Laravel Sail の Xdebug の設定について

vagrant を使って VirtualBox に構築した Linux VM 上の Docker で Laravel Sail を動作させているときの Xdebug 設定の備忘録

検証環境

Windows10 Home Edition (version 22H2)
VirtualBox 6.1.40
vagrant 2.3.4

# Docker Host OS
ubuntu 22.04.1 LTS

Docker version 20.10.21, build baeda1f

発生した問題について

上記 Docker 環境で動作している Laravel Sail に WindowsVSCode から Dev Container でアタッチしてデバッグしようとしたところ、ブレークポイントを設定しても停止しなかった
調査したところ xdebug.client_host が不正だったため VSCodeXdebug からの通知が届いていなかったことが原因と判明した

xdebug.client_host の設定値ついて

xdebug.client_host には Xdebug クライアント (今回は WindowsVSCode) の IP アドレスを設定する必要がある
WSL2 では自動的に host-gateway に設定されるが VirtualBox ではそのような変数はないため明示的に指定する

コンテナから Windows へのアクセス

コンテナから Windows へのアクセスはデフォルトルートを通じて行うことが可能
デフォルトルートは ubuntu 上で ip r と入力することで確認できる

$ ip r
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100
10.0.2.3 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-3c28ac761546 proto kernel scope link src 172.18.0.1 linkdown
172.19.0.0/16 dev br-95a8cdd8ea38 proto kernel scope link src 172.19.0.1
192.168.33.0/24 dev enp0s8 proto kernel scope link src 192.168.33.10

1行目の default がデフォルトルートで、この場合 IP アドレス 10.0.2.2 を使って Windows へアクセス可能となる

Laravel Sail の Xdebug 設定

.env に下記内容を追加する
.env

SAIL_XDEBUG_MODE=develop,debug
SAIL_XDEBUG_CONFIG="client_host=10.0.2.2"

devcontainer.json に下記内容を追加する
.devcontainer/devcontainer.json

         "forwardPorts": [
                9003
         ]

.vscode フォルダに launch.json を作成する
.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "stopOnEntry": true,
            "pathMappings": {
                "/var/www/html": "${workspaceFolder}"
            }
        }
    ]
}

コンテナイメージを再構築する

$ ./vendor/bin/sail build --no-cache

動作確認

コンテナを起動する

$ ./vendor/bin/sail up -d

VSCodeRemote SSHubuntu に接続した後、 Dev Container でコンテナにアタッチする

PHP Debug拡張機能をインストールする

Chrome でテストする場合は Xdebug helper エクステンションをインストールする

停止させたい箇所にブレイクポインタを設定する

デバッグ実行開始

Chromeデバッグ対象の URL を開く

Xdebug helper エクステンションのアイコンをクリックして Debug を選択

再度 URL を開くとブレイクポインタで停止することを確認する

参考サイト

readouble.com

xdebug.org

chrome.google.com

Vagrant で ubuntu 22.04 + Docker 開発環境

基本的に下記記事の手順で作成可能です

takaya030.hatenablog.com

Vagrantfile の内容が一部異なるので Vagrantfile のみ記載します
docker compose v1 は開発が停止しているためインストールしないようにしました
最新の docker では docker compose v2 がデフォルトで組み込まれています

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/jammy64"

  config.vm.box_check_update = false

  config.vm.network "private_network", ip: "192.168.33.11"

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = true
  
    # Customize the amount of memory on the VM:
    vb.memory = "2048"
  end

  config.vm.provision :docker

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update -y

    gpasswd -a vagrant docker

    mkdir -p /etc/systemd/system/docker.service.d
    touch /etc/systemd/system/docker.service.d/options.conf
    echo '[Service]' > /etc/systemd/system/docker.service.d/options.conf
    echo 'ExecStart=' >> /etc/systemd/system/docker.service.d/options.conf
    echo 'ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:2375' >> /etc/systemd/system/docker.service.d/options.conf

    touch /etc/docker/daemon.json
    echo '{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}' > /etc/docker/daemon.json
    chmod 600 /etc/docker/daemon.json

    systemctl daemon-reload
    systemctl restart docker

    if [ ! -d "/home/vagrant/google-cloud-sdk" ]; then
      curl https://sdk.cloud.google.com > /tmp/install.sh
      sudo -u vagrant -i bash /tmp/install.sh --disable-prompts --install-dir=/home/vagrant
      sudo -u vagrant -i echo '# The next line updates PATH for the Google Cloud SDK.' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo 'if [ -f '\\''/home/vagrant/google-cloud-sdk/path.bash.inc'\\'' ]; then . '\\''/home/vagrant/google-cloud-sdk/path.bash.inc'\\''; fi' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo '# The next line enables shell command completion for gcloud.' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo 'if [ -f '\\''/home/vagrant/google-cloud-sdk/completion.bash.inc'\\'' ]; then . '\\''/home/vagrant/google-cloud-sdk/completion.bash.inc'\\''; fi' >> /home/vagrant/.bashrc
      rm -vf /tmp/install.sh
    fi
  SHELL
end

参考サイト

cloud.google.com

変更履歴

Laravel Sail インストール時に発生したエラーと解決方法

Laravel 公式サイトで紹介されていた方法で Laravel Sail をインストールしようとしたところ、エラーが発生して処理が中断したのでその解決方法の備忘録

検証環境

Windows10 Home Edition (version 21H2)
VirtualBox 6.1.32
vagrant 2.2.19

# Docker Host OS
ubuntu 20.04.3 LTS (Focal Fossa)

Docker version 20.10.8, build 3967b7d
docker-compose version 1.29.2, build 5becea4c

インストール

発生したエラーについて

下記コマンドでインストールしようとしたところ途中でエラーが発生して中断した

$ curl -s https://laravel.build/example-app | bash

エラーメッセージ

  [ErrorException]
  file_get_contents(/opt/example-app/vendor/symfony/error-handler/Resources/bin/patch-type-declarations): Failed to open stream: No such file or directory

インストールスクリプトの中で laravel new が使われていて、そこでエラーが発生していた

解決方法

composer を使ってインストールすることで解決した

$ docker pull composer
$ docker run --rm -it --volume $PWD:/app composer create-project laravel/laravel example-app
$ cd example-app
$ docker run --rm -it --volume $PWD:/app composer require laravel/sail --dev
$ docker run --rm -it --volume $PWD:/app composer php artisan sail:install --devcontainer

 Which services would you like to install? [mysql]:
  [0] mysql
  [1] pgsql
  [2] mariadb
  [3] redis
  [4] memcached
  [5] meilisearch
  [6] minio
  [7] mailhog
  [8] selenium
 > 0

docker build

発生したエラーについて

インストール完了後、 ./vendor/bin/sail up でコンテナを起動しようとしたところ下記エラーが発生

E: Problem executing scripts APT::Update::Post-Invoke 'rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true'
E: Sub-process returned an error code

Docker イメージのビルド中にエラーが発生していた

解決方法

デフォルトは context./vendor/laravel/sail/runtimes/8.1 が指定されていた
./vendor/laravel/sail/runtimes/8.0 に変更したところ正常にビルドされた

docker-compose.yml を変更

--- a/docker-compose.yml  Sat May 14 18:28:33 2022
+++ b/docker-compose.yml  Sat May 14 16:36:36 2022
@@ -3,11 +3,11 @@
 services:
     laravel.test:
         build:
-            context: ./vendor/laravel/sail/runtimes/8.1
+            context: ./vendor/laravel/sail/runtimes/8.0
             dockerfile: Dockerfile
             args:
                 WWWGROUP: '${WWWGROUP}'
-        image: sail-8.1/app
+        image: sail-8.0/app
         extra_hosts:
             - 'host.docker.internal:host-gateway'
         ports:

sail build で再ビルド

$ ./vendor/bin/sail build --no-cache

動作確認

sail up で起動

$ ./vendor/bin/sail up -d

http://<docker-host-ip>/ を web ブラウザでアクセスして以下の画面が表示されたら成功

参考サイト

laravel.com

zenn.dev

hub.docker.com

Python から MySQL に接続するサンプルプログラムを Docker で動かす

Python の mysqlclient を使ったサンプルプログラムを Docker で動かしたときの手順メモ

検証環境

Windows10 Home Edition (version 21H2)
VirtualBox 6.1.32
vagrant 2.2.19

# Docker Host OS
ubuntu 20.04.3 LTS (Focal Fossa)

Docker version 20.10.8, build 3967b7d
docker-compose version 1.29.2, build 5becea4c

ファイル構成

test
  │  Dockerfile
  │  docker-compose.yml
  │  example.py

Dockerfile

FROM python:3.9.10-slim-buster

RUN apt-get update && \
    apt-get -y install gcc libmariadb-dev && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip install mysqlclient

COPY ./example.py /app/example.py

WORKDIR /app

CMD python ./example.py

docker-compose.yml

version: "3.4"
services:
  app: 
    build:
      context: .
      dockerfile: ./Dockerfile
    image: "takaya030/pymysql"
    container_name: pymysqlclient
  db:
    image: mysql:5.7.37
    container_name: mysql_host
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test_database
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - 3306:3306

example.py

import MySQLdb
import time

# MySQLの起動を待つため
time.sleep(5)

connection = MySQLdb.connect(
    host='db',
    user='docker',
    passwd='docker',
    db='test_database')
cursor = connection.cursor()
 
cursor.execute("""SHOW CREATE DATABASE test_database;
""")

myresult = cursor.fetchall()

for row in myresult:
    print(row)

connection.close()

イメージのビルド

$ cd test

$ docker-compose build app

動作確認

Docker コンテナの起動

$ cd test

$ docker-compose up

正常動作していれば 5 秒後に下記のログが出力される

pymysqlclient | ('test_database', 'CREATE DATABASE `test_database` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */')

Ctrl + C でコンテナを終了させる

参考サイト

zenn.dev

qiita.com

www.geeksforgeeks.org

Laravel の artisan コマンドの引数バリデーションを行う

artisan コマンドの引数バリデーションを行うパッケージ cerbero/command-validator についてのメモ

検証環境

Windows10 Home Edition (version 21H1)

$ php --version
PHP 7.4.9 (cli) (built: Aug  4 2020 11:52:41) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
    with Xdebug v2.8.1, Copyright (c) 2002-2019, by Derick Rethans

$ php artisan --version
Laravel Framework 8.73.0

cerbero/command-validator パッケージについて

リクエストに適用するバリデーションルールと同じ記述方法で artisan コマンドの引数のバリデーションが出来るパッケージ

github.com

インストール方法

$ composer require cerbero/command-validator

検証用 artisan コマンド

検証用として 2 つの数値を引数に与えるとその和を表示する artisan コマンドを作成する

$ php artisan make:command Addition

app/Console/Commands/Addition.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class Addition extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'addition {num1} {num2}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Addition of two numbers';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->info($this->argument('num1') + $this->argument('num2'));
        return Command::SUCCESS;
    }
}

動作確認

$ php artisan addition 1 2
3

$ php artisan addition 1 2.5
3.5

$ php artisan addition 1.25 2.17
3.42

# 引数に数値以外を与えるとエラーになるためバリデーションで防止したい
$ php artisan addition 1 abc

   ErrorException

  A non-numeric value encountered

検証用 artisan コマンド (バリデーションあり)

cerbero/command-validator を使って引数をバリデーションするように変更

app/Console/Commands/Addition.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Cerbero\CommandValidator\ValidatesInput;

class Addition extends Command
{
    use ValidatesInput;

    protected function rules()
    {
        return [
            'num1' => 'numeric',
            'num2' => 'numeric',
        ];
    }

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'addition {num1} {num2}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Addition of two numbers';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->info($this->argument('num1') + $this->argument('num2'));
        return Command::SUCCESS;
    }
}

動作確認

$ php artisan addition 1 2
3

$ php artisan addition 1 2.5
3.5

$ php artisan addition 1.25 2.17
3.42

$ php artisan addition 1 abc


  The num2 must be a number.

バリデーションによって数値以外を受け付けないことを確認

Lumen8 で環境変数 APP_ENV に応じて .env ファイルを切り替える

検証環境

Windows10 Home Edition (version 21H1)

$ php --version
PHP 7.4.9 (cli) (built: Aug  4 2020 11:52:41) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
    with Xdebug v2.8.1, Copyright (c) 2002-2019, by Derick Rethans

$ php artisan --version
Laravel Framework Lumen (8.2.4) (Laravel Components ^8.0)

Lumen8 の .env ファイルの読み込みについて

Lumen8 では bootstrap/app.php の先頭にある下記の部分で読み込んでいます

(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
    dirname(__DIR__)
))->bootstrap();

Laravel\Lumen\Bootstrap\LoadEnvironmentVariables クラスのソースを確認するとコンストラクタで .envディレクトリだけでなくファイル名も指定可能になっていました

vendor/laravel/lumen-framework/src/Bootstrap/LoadEnvironmentVariables.php

<?php

namespace Laravel\Lumen\Bootstrap;

use Dotenv\Dotenv;
use Dotenv\Exception\InvalidFileException;
use Illuminate\Support\Env;
use Symfony\Component\Console\Output\ConsoleOutput;

class LoadEnvironmentVariables
{
    /**
     * The directory containing the environment file.
     *
     * @var string
     */
    protected $filePath;

    /**
     * The name of the environment file.
     *
     * @var string|null
     */
    protected $fileName;

    /**
     * Create a new loads environment variables instance.
     *
     * @param  string  $path
     * @param  string|null  $name
     * @return void
     */
    public function __construct($path, $name = null)
    {
        $this->filePath = $path;
        $this->fileName = $name;
    }

    /**
     * Setup the environment variables.
     *
     * If no environment file exists, we continue silently.
     *
     * @return void
     */
    public function bootstrap()
    {
        try {
            $this->createDotenv()->safeLoad();
        } catch (InvalidFileException $e) {
            $this->writeErrorAndDie([
                'The environment file is invalid!',
                $e->getMessage(),
            ]);
        }
    }

    /**
     * Create a Dotenv instance.
     *
     * @return \Dotenv\Dotenv
     */
    protected function createDotenv()
    {
        return Dotenv::create(
            Env::getRepository(),
            $this->filePath,
            $this->fileName
        );
    }

    /**
     * Write the error information to the screen and exit.
     *
     * @param  string[]  $errors
     * @return void
     */
    protected function writeErrorAndDie(array $errors)
    {
        $output = (new ConsoleOutput)->getErrorOutput();

        foreach ($errors as $error) {
            $output->writeln($error);
        }

        exit(1);
    }
}

環境変数 APP_ENV に応じて .env を切り替える変更

bootstrap/app.php を下記のように変更することで APP_ENV の値に応じて読み込む .env が切り替わります
例えば APP_ENV=prd のときは .env.prd が読み込まれます

bootstrap/app.php

$env = env('APP_ENV');
$env_file = '.env.'.$env;

if (!file_exists(dirname(__DIR__).'/'.$env_file)) {
    $env_file = null;
}

(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
    dirname(__DIR__),
    $env_file
))->bootstrap();

Vagrant で ubuntu 20.04 + Docker 環境構築

VagrantVirtualBoxubuntu 20.04 の VM を構築したときの手順メモ

検証環境

Windows10 Home Edition (version 21H1)

chocolatey のインストール

こちらのサイトからインストールします
自分は PowerShell のインストールコマンドでインストールしました

chocolatey.org

Windows のソフトのインストール

PowerShell を管理者として実行
chocolatey で VirtualBoxvagrant、docker-cli、docker-compose をインストールする

PS D:\> choco install -y virtualbox
PS D:\> choco install -y vagrant
PS D:\> choco install -y docker-cli
PS D:\> choco install -y docker-compose

インストールが完了したら各ツールの動作確認

D:\>vagrant version
Installed Version: 2.2.18
Latest Version: 2.2.18

You're running an up-to-date version of Vagrant!

D:\>docker -v
Docker version 19.03.12, build 0ed913b8-

D:\>docker-compose -v
docker-compose version 1.29.2, build 5becea4c

vagrantプラグインのインストール

D:\>vagrant plugin install vagrant-disksize
D:\>vagrant plugin install vagrant-vbguest
D:\>vagrant plugin install vagrant-docker-compose

インストールされたか確認

D:\>vagrant plugin list
vagrant-disksize (0.1.3, global)
vagrant-docker-compose (1.5.1, global)
vagrant-vbguest (0.30.0, global)

Vagrantfile の作成

作業用ディレクトリを作成して vagant init を実行します

D:\>mkdir vagrant\focal64

D:\>cd vagrant\focal64

D:\vagrant\focal64>vagrant init ubuntu/focal64

作成された Vagrantfile を下記の内容に変更します。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/focal64"

  config.vm.box_check_update = false

  config.vm.network "private_network", ip: "192.168.33.11"

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = true
  
    # Customize the amount of memory on the VM:
    vb.memory = "2048"
  end

  config.vm.provision :docker
  config.vm.provision :docker_compose, compose_version: "1.29.2"

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update -y

    gpasswd -a vagrant docker

    mkdir -p /etc/systemd/system/docker.service.d
    touch /etc/systemd/system/docker.service.d/options.conf
    echo '[Service]' > /etc/systemd/system/docker.service.d/options.conf
    echo 'ExecStart=' >> /etc/systemd/system/docker.service.d/options.conf
    echo 'ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:2375' >> /etc/systemd/system/docker.service.d/options.conf

    touch /etc/docker/daemon.json
    echo '{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}' > /etc/docker/daemon.json
    chmod 600 /etc/docker/daemon.json

    systemctl daemon-reload
    systemctl restart docker

    if [ ! -d "/home/vagrant/google-cloud-sdk" ]; then
      curl https://sdk.cloud.google.com > /tmp/install.sh
      sudo -u vagrant -i bash /tmp/install.sh --disable-prompts --install-dir=/home/vagrant
      sudo -u vagrant -i echo '# The next line updates PATH for the Google Cloud SDK.' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo 'if [ -f '\\''/home/vagrant/google-cloud-sdk/path.bash.inc'\\'' ]; then . '\\''/home/vagrant/google-cloud-sdk/path.bash.inc'\\''; fi' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo '# The next line enables shell command completion for gcloud.' >> /home/vagrant/.bashrc
      sudo -u vagrant -i echo 'if [ -f '\\''/home/vagrant/google-cloud-sdk/completion.bash.inc'\\'' ]; then . '\\''/home/vagrant/google-cloud-sdk/completion.bash.inc'\\''; fi' >> /home/vagrant/.bashrc
      rm -vf /tmp/install.sh
    fi
  SHELL
end

仮想マシンの起動

vagrant up仮想マシンを起動します

D:\vagrant\focal64>vagrant up

vagrant ssh仮想マシンにログインします。

D:\vagrant\focal64>vagrant ssh

Docker の動作確認

プロビジョニングが正常に実行されていれば docker コマンドが使用可能になっています

vagrant@ubuntu-focal:~$ docker -v
Docker version 20.10.8, build 3967b7d

vagrant@ubuntu-focal:~$ docker-compose -v
docker-compose version 1.29.2, build 5becea4c

vagrant@ubuntu-focal:~$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:7d91b69e04a9029b99f3585aaaccae2baa80bcf318f4a5d2165a9898cd2dc0a1
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Windows からのリモート接続の確認

Windows の docker コマンドが ubuntu の docker エンジンにリモート接続可能か確認します

D:\>set DOCKER_HOST=tcp://192.168.33.11:2375

D:\>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              d1165f221234        6 months ago        13.3kB

D:\>docker run --rm hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

参考サイト

takaya030.hatenablog.com

qiita.com

qiita.com

www.vagrantup.com

qiita.com

dockerlabs.collabnix.com

docs.docker.jp

変更履歴