takaya030の備忘録

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

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

f:id:takaya030:20210911225900p:plain

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
  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

Docker で ASP.NET Core 5.0 を動かす

VagrantVirtualBox に構築した ubuntu 18.04 + Docker 環境で ASP.NET Core 5.0 を動かしたときの手順メモ

検証環境

# Host OS
Windows10 Home Edition
VirtualBox 6.1.22
Vagrant 2.2.16

# Guest OS
ubuntu 18.04.5 LTS (Bionic Beaver)
Docker version 20.10.7, build f0df350

サンプルアプリのダウンロード

マイクロソフトが公開している dotnet-docker のサンプルをダウンロードします。

$ git clone https://github.com/dotnet/dotnet-docker

ビルドと実行

$ cd dotnet-docker/samples/aspnetapp
$ docker build -t aspnetapp .
$ docker run -it --rm -p 5000:80 --name aspnetcore_sample aspnetapp

動作確認

http://<GuestOSのIP>:5000 を WEB ブラウザで開いて以下の画面が表示されれば成功です。 f:id:takaya030:20210828182357p:plain

参考サイト

docs.microsoft.com

ubuntu 18.04 に apt-get で gcloud をインストール

VagrantVirtualBox に構築した ubuntu 18.04 環境に gcloud をインストールしたときの手順メモ

検証環境

Windows10 Home Edition
VirtualBox 6.0.18
Vagrant 2.2.9

C:\>vagrant box list
ubuntu/bionic64   (virtualbox, 20200916.0.0)

gcloud コマンドのインストール

以下の Google のサイトに記載されていた手順でインストールできました。

cloud.google.com

# Add the Cloud SDK distribution URI as a package source
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list

# Import the Google Cloud public key
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -

# Update the package list and install the Cloud SDK
sudo apt-get update && sudo apt-get install google-cloud-sdk

SDK の初期化

下記のコマンドで SDK を初期化します。

$ gcloud init --console-only

gcloud 認証情報ヘルパー

docker コマンドで Container Registry へイメージの push/pull を可能にするため認証情報ヘルパーを設定します。

下記のコマンドでユーザー認証情報から認証を構成します

$ gcloud auth login

次のコマンドで Docker を構成します。

$ gcloud auth configure-docker

$HOME/.docker/config.json に認証情報が保存されます。

動作確認

Container Registry へ push したいイメージを下記のようにタグ付けします
(gcr.io はプッシュ先レジストリのホストネーム)
(TAG を省略した場合は latest になる)

$ docker tag SOURCE_IMAGE gcr.io/PROJECT_ID/IMAGE:TAG

下記コマンドで push します

$ docker push gcr.io/PROJECT_ID/IMAGE:TAG

参考サイト

cloud.google.com

cloud.google.com

cloud.google.com