20200724のdockerに関する記事は18件です。

pleasanter+PostgreSQL+SSL+docker な構成を作ってみた

概要

  • pleasanter、docker、PostgreSQL、SSLの環境を作りました。
  • gitsを駆使したのでほぼコピペでpleasanterが動くようになりました。
  • SSLにも対応しているので、インターネットに置いてお試しとして使う事が出来ると思います。

作ったもの

pleasanter-docker-PostgreSQL

使い方

ドメイン

SSLを使う場合、 ドメイン取得が必須となります。
適当なドメインを用意しまょう!

aws ec2セットアップ (必要な人だけ)

今回はec2を使いました。
実際の所は、dockerが動けば何でもよいと思います。
ただし、メモリが1Gくらい必要でスワップが無い状態だとうまく起動させることが出来ませんでした。
(aws EC2 t2-nanoのデフォルトだとスワップが無い。)

以下shellで順次設定していきます。

gits shell swap 有効化

次に、amazon linuxを入れた直後だとdockerが使えないため、
以下shellで有効化します。

gits shell amazon linux docker有効化

pleasanter準備

いよいよ本題です。
pleasanterの準備を行います。
gitリポジトリをクローンして良いパスに移動して以下コマンドを実行してください。

gits shell pleasanter準備

なお、sslが不要な方はコマンドの中で実施している「git checkout ssl」を外して下さい。

ドメイン設定

sslを使う方はドメインを設定してください。
gitで落ちてきた設定ファイルの中から、
以下ファイルの★の部分を変更します。

docker-compose.yml
~ 抜粋 ~
  # 通信を暗号化
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    links:
      - pleasanter-web
    restart: always
    environment:
      DOMAINS: 'wordpress.example.com -> http://pleasanter-web' ← ★1
      # 本番モードへ切り替え
      # STAGE: 'production' ← ★2
      # 証明書を強制的に再取得する
      # FORCE_RENEW: 'true'
~ 抜粋 ~
意味
★1 wordpress.example.comをご自分のドメイン名に置き換えてください。
★2 コメントを外すとLet's Encrypt から発行された証明書を使います。コメント付きだとオレオレ証明書で動きます。

起動

普通に起動してください。

docker-compose up -d

指定されたドメインにアクセスするとユーザーは初期設定となっているので、
以下アカウント情報でログインしてください。

user: Administrator
pass: pleasanter

よく考えたら...

正規版pleasanterの小規模プランだと1000円/月との事です。
aws EC2 t2-nanoでも月1000円くらいかかるので、
pleasanterの開発に貢献する意味でも正規版を買うようにしましょう!

料金プラン

参考

Pleasanterをサクッと起動できるcompose
https-portalを使ってみて、個人的にぶつかりそうな壁の解決方法
docker で全自動 Let's encrypt

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker for Windows をWSL2で利用する。

Docker for Windows をWSL2で使う

インストール

こちらからダウンロードしてきます。

ダウンロードしたファイルを実行すると、以下のような画面が表示されるので、そのままOKを選択
image.png

こんな感じの画面でインストールが行われる。
image.png

インストールが終わると、こんな画面が表示される。「Close and restart」を押下すると再起動されてインストールが完了する
image.png

再起動が終わるとこんな画面が表示されるので「start」を選択する
image.png

チュートリアルが始まるので適当にスキップします。

WSL2のUbuntuでDockerを使えるようにする

設定画面を表示して、以下の通り、WSL2のUbuntuでDockerを利用できるようにする。

image.png

Ubuntu側で確認する

wsl2のターミナルを起動して、「docker」コマンドを実行

image.png

無事認識されました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Desktop をWSL2で利用する。

Docker Desktop をWSL2で使う

インストール

こちらからダウンロードしてきます。

ダウンロードしたファイルを実行すると、以下のような画面が表示されるので、そのままOKを選択
image.png

こんな感じの画面でインストールが行われる。
image.png

インストールが終わると、こんな画面が表示される。「Close and restart」を押下すると再起動されてインストールが完了する
image.png

再起動が終わるとこんな画面が表示されるので「start」を選択する
image.png

チュートリアルが始まるので適当にスキップします。

WSL2のUbuntuでDockerを使えるようにする

設定画面を表示して、以下の通り、WSL2のUbuntuでDockerを利用できるようにする。

image.png

Ubuntu側で確認する

wsl2のターミナルを起動して、「docker」コマンドを実行

image.png

無事認識されました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでRedisコンテナを立ち上げLaravelで読み書きする

はじめに

DockerでRedisコンテナを立ち上げLaravelから読み書きしてみましたので、
Redisコンテナを立ち上げるまでの最小限の構成を紹介します。

やりたいこと

  • DockerでRedisコンテナを立ち上げたい
  • Redisのデータを永続化したい
  • LaravelからRedisのデータを読み書きしたい

この記事で説明しないこと

  • Redis以外のDocker構成
  • Laravelのインストール手順

ディレクトリ構成

.
├── data
│   └── redis
│       └── appendonly.aof(コンテナ起動時に作成されます)
├── docker-file
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── volumes
│   └── www
└── docker-compose.yml

各ファイルの内容

docker-compose.yml

データ永続化の為にdataフォルダをマウントしています。

また、redisコンテナを立ち上げ直すたびにIPアドレスが変わっては不便なのでnetworksで固定IPを割り振るようにしています。

docker-compose.yml
version: '3.3'

services:
  php:
    container_name: php
    build: ./docker-file/php
    volumes:
      - ./volumes/www:/var/www
    networks:
      app_net:
        ipv4_address: 172.16.238.2

  nginx:
    image: nginx
    container_name: nginx
    ports:
      - 8080:80
    volumes:
      - ./volumes/www:/var/www
      - ./docker-file/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
    networks:
      app_net:
        ipv4_address: 172.16.238.3

  redis:
    image: "redis:latest"
    container_name: redis
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
    volumes:
      - "./data/redis:/data"
    networks:
      app_net:
        ipv4_address: 172.16.238.4

networks:
  app_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.16.238.0/24

docker-file/nginx/default.conf

default.conf
server {
  listen 80;

  root  /var/www/public;
  index index.php;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   php:9000;
    fastcgi_index  index.php;

    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
  }
}

docker-file/php/Dockerfile

公式でPhpRedis PHP拡張が推奨されている為、phpredisをgit cloneしています。

LaravelでRedis使用するには、PECLを使用してPhpRedis PHP拡張をインストールすることを推奨します。インストール方法は複雑ですが、Redisをヘビーユースするアプリケーションではより良いパフォーマンスが得られます

FROM php:7.3-fpm
COPY php.ini /usr/local/etc/php/

RUN apt-get update \
  && apt-get install -y zlib1g-dev libzip-dev libpq-dev iputils-ping net-tools git
RUN git clone https://github.com/phpredis/phpredis.git /usr/src/php/ext/redis
RUN docker-php-ext-install zip pgsql pdo_pgsql redis

COPY --from=composer /usr/bin/composer /usr/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

WORKDIR /var/www

RUN composer global require "laravel/installer"

docker-file/php/php.ini

php.ini
[Date]
date.timezone = "Asia/Tokyo"

[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

実行

docker-composeで起動します。

$ docker-compose up -d
Creating network "redis-docker_app_net" with driver "bridge"
Creating php   ... done
Creating redis ... done
Creating nginx ... done

Laravelから読み書きする

config/database.phpを設定する必要がありますが、基本的には初期設定のままで問題ありません。
参考:Redis 6.x Laravel

書き込み、読み込み

/app/Http/Controllers/RedisController.php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis;

class RedisController extends Controller
{
    /**
     * Redisへデータをセット
     */
    public function setRedis($id)
    {
        Redis::set('test', $id);

        return;
    }

    /**
     * Redisのデータを取得
     */
    public function getRedis()
    {
        $redis_data = Redis::get('test');

        return;
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP7.2 × DockerでgRPCクライアントを使うための環境構築

Goでクライアントを作るときには、brewgo getでパッケージをいくつか入れるだけで済むのですが、PHPの方ではいくつかハマりどころがあったのでまとめました。

前提

  • protoコマンドがインストールされている
  • 使用するRPC方式はUnaryRPCである
  • コード生成はローカル環境で行う

扱うprotoファイル

下記のprotoに少し変更をかけたものを扱います。
https://grpc.io/docs/languages/php/quickstart/

hello.proto
package hello;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

コード生成

下記ページを参考にしました。
https://grpc.io/docs/languages/php/quickstart/

コード生成用のPHPプラグインを追加

protoファイルからPHP用の各種クラスを生成するために、grpc_php_plugin を入れる必要があります。

$ git clone -b v1.30.0 https://github.com/grpc/grpc
$ cd grpc && git submodule update --init && make grpc_php_plugin

すると、ソースを展開したディレクトリに bins/opt/grpc_php_plugin が生成されます。

コード生成実行

下記コマンドを入力します。

$ protoc --proto_path=proto \
  --php_out=src/gen \
  --grpc_out=src/gen \
  --plugin=protoc-gen-grpc=./grpc/bins/opt/grpc_php_plugin \
  ./proto/hello.proto

この時のオプションとして、

  • --proto_path にはprotoファイルが配置されているディレクトリを指定する
  • --php_out--grpc_out は同じディレクトリを指定する
  • --plugin=protoc-gen-grpc= に、先ほどプラグインをインストールしたディレクトリの bins/opt/grpc_php_plugin を指定する

を行います。
これでコード生成はOKです。

クライアント環境準備

インストールするパッケージは下記ページを参考にしました。
https://cloud.google.com/php/grpc?hl=ja#php-implementation

Dockerの上で動かしたPHPで、gRPCのリクエストを送るための環境を構築します。

php.ini

grpc.so 拡張パッケージの記述がポイントです。

php.ini
[Date]
date.timezone = "Asia/Tokyo"

[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

extension = grpc.so

Dockerfile

peclでgrpcパッケージを入れることがポイントです。

FROM php:7.2-stretch

RUN apt-get update -y \
    && apt-get install -y zip autoconf zlib1g-dev \
    && apt-get clean

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY php.ini /usr/local/etc/php/php.ini
RUN pecl install grpc

WORKDIR /var/local
COPY . .
RUN composer install

composer.json

ここでは先ほどのコード生成によってファイルが格納された先を src/gen として扱っています。

composer.json
{
    "autoload": {
        "psr-4": {
            "Hello\\": "src/gen/Hello",
            "GPBMetadata\\": "src/gen/GPBMetadata"
        }
    },
    "require": {
        "php": ">=7.2",
        "google/protobuf": ">=3.0",
        "grpc/grpc": ">=v1.27.0"
    },
    "repositories": [
        {
          "type": "vcs",
          "url": "https://github.com/stanley-cheung/Protobuf-PHP"
        }
    ]
}

ポイントは、

  • google/protobuf パッケージのインストール
  • grpc/grpc パッケージのインストール
  • コード生成されたクラスをautoloadで読み込み指定する

ことです。

docker-compose.yaml

先ほどのphp.iniを、ボリュームマウントでコンテナに配置することがポイントです。

docker-compose.yaml
version: "3"
services:
  php:
    build: .
    volumes:
      - ./php.ini:/usr/local/etc/php/php.ini
      - .:/var/local/
    ports:
      - 80:80

クライアント実装

実装例です。

srcipts/RunHello.php
<?php

use Hello\GreeterClient;
use Hello\HelloRequest;

$hostname = 'localhost:8000';
$client = GreeterClient($hostname, [
    'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);

$request = new HelloRequest();
$request->setName("DummyName");
list($reply, $status) = $client->SayHello($request)->wait();
$message = $reply->getMessage();

この時vendor配下に \Grpc\ChannelCredentials クラスが存在せず、エディタでは警告等が出ます。
しかしPHPのgRPC拡張によって、必要なライブラリがDocker側にインストールされているため実行時には正常に通ります。
(個人的にはここがハマりポイントでした)

実行

オートローダーを読み込んで、クライアント実装のスクリプトを読み込めば実行されます。

$ docker-compose run --rm php -a
php> require_once('vendor/autoload.php');
php> require_once('scripts/RunHello.php');

あとはこのクライアントをクラスに閉じ込めたり、composerのパッケージ化などを行えばWebサーバー等にも組み込むことができます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker for Windowsを入れるまでにやったこと

とりあえず、雑にやったこと残します
あとで整形します

やったこと

  • Windowsの更新
  • MicrosoftStoreからUbuntのインストール
  • WLS2へのアップグレード
  • Docker for Windowsのインストール

Windowsのバージョンチェック

[Win + R]でファイル名を指定して実行winverと入力
image.png
この段階で、バージョンが19018以下だとDocker for Windowsはインストールできません。

Windowsの更新

というわけでWindowsそのものをアップデートします。
Windows 10 May 2020 Update

[Update now]ボタンから更新プログラムをダウンロードします。
image.png

Windows10Upgrade9252.exeファイルがダウンロードされるので、クリックして起動します。

途中の経過をキャプチャ取り忘れましたが、スタートして30分くらいで完了し、再起動を求められます。
image.png

再起動後にバージョンを確認すると、19041になりました

image.png

MicrosoftStoreからUbuntのインストール

もともとWindows使うの久しぶりでWLSもまともに使ってなかったので、wslを起動しようとしても以下のようになります。
image.png

なので、MicrosoftStoreからLinux(Ubunts)をインストールします。

MicrosoftStoreを起動します。
image.png

Ubuntu20.04.LTSを選びます。
ここは別に好きなLinuxにしてもらっても大丈夫です。
image.png

インストールをクリックします。
image.png

インストールが完了したら起動ボタンをクリックします。
image.png

起動するとターミナルが開くので、username、passwordを設定します。
image.png

ここまででUbuntuの設定は終わりです。
image.png

WLS2へのアップグレード

Windowsの機能確認と更新

PowerShellを管理者で起動します。
image.png

以下のコマンドでWindowsの機能確認ができます

dism.exe /online /get-features

コマンド実行時に以下の2つが有効になっているかを確認します

機能名 : Microsoft-Windows-Subsystem-Linux
状態 : 有効

機能名 : VirtualMachinePlatform
状態 : 有効

なっていない場合は以下のコマンドで有効にしてください

  • Microsoft-Windows-Subsystem-Linux
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
  • VirtualMachinePlatform
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

Linuxカーネルの更新

インストール済みのLinuxディストリビューションを確認します。

wsl --list --verbose
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         1

今はVersion1になっているのでコマンドでVersion2に上げるのですが、このままやると
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です
と言われてしまうので、Linuxのカネールを更新します。

以下のページにアクセスして、パッケージのダウンロードをします。
WSL 2 Linux カーネルの更新
image.png

wsl_update_x64ファイルがダウンロードされるので、クリックして起動します。

image.png

[Next]を押します

image.png

[Finishi]を押して完了です。

LinuxディストリビューションをWSL2に設定

以下のコマンドでUbuntuをWSL2にアップデートします

wsl --set-version Ubuntu-20.04 2

ディストリビューションを確認します。

wsl --list --verbose
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         2

変更されました。

WSL2をデフォルトに設定

WSLからデフォルトバージョンをWSL2に変更します

wsl --set-default-version 2

Docker for Windowsのインストール

もともとはコレがやりたかった。
随分遠回りしたけど、インストールやってきます。

Docker Desktop for Windows

Docker Desktop Installerファイルがダウンロードされるので、クリックして起動します。

image.png

[OK]で先に進みます

image.png

インストールが進みます

image.png

完了です、[Close and log out]でログアウトします
このとき再起動がかかります

再起動後にDocker for windowsの設定画面でましたが、正直使うのはDockerのコマンドだけなので飛ばしました。

一応起動中は以下の場所に常駐していて、Dashboardから画面は開けます。
image.png

まとめ

ともかく長かった。
WindowsのDockerがめんどくさいとは聞いていたが、ここまでとは・・・
ただ、WSL2になってDockerの実行環境がLinuxになったのはましになったと思う。

というわけで、本当にやりたかったことはこれからやります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでPHP7.4のLaravel開発環境を作成

PHP7.4のLaravel開発環境を、Docker-Composeで構築して、Laravelの新規プロジェクトを作成して起動してみるところまで確認してみます。
データベースには「MariaDB」を使います。

環境

この記事を書くにあたって使用した環境です。どれも、2020年7月時点の最新バージョンを使用しているハズ。

Docker

Name Version
docker 19.03.1
docker-compose 1.24.1

Web

今回は、Webサーバーに「Apache」を使用します。

Name Version
PHP 7.4
Apache 2.4.38
Laravel 7.21.0

DB

データベースは「MariaDB」です。データベース管理ツールの「Adminer」も入れておきます。

Name Version
MariaDB 10.5.4
Adminer 4.7.7

フォルダ構成

今回は、次のようなフォルダ構成にします。

[Project_ROOT]
├ docker
│ └ web
│   ├ apache
│   │ └ 000-default.conf
│   ├ php
│   │ └ php.ini
│   └ Dockerfile  
├ mysql
│ ├ data
│ └ initdb
└ docker-compose.yml

docker-compose.yml

version : "3"
services:
  web:
    container_name: web
    build: ./docker/web
    ports:
      - 80:80
    privileged: true
    volumes:
      - ./server:/var/www/html

  db:
    image: mariadb
    restart: always
    ports:
      - 3307:3306
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/initdb:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_ROOT_PASSWORD=pwd
      - MYSQL_DATABASE=test
      - MYSQL_USER=user
      - MYSQL_PASSWORD=pwd

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

Dockerfile (PHP+Apache)

docker/webにwebコンテナ 構築用の「Dockerfile」を作成します。
PHP+Apacheのイメージをベースに、各種ライブラリとComposer、Laravelをインストールします。

FROM php:7.4-apache
COPY ./php/php.ini /usr/local/etc/php/
COPY ./apache/*.conf /etc/apache2/sites-enabled/

RUN apt-get update \
  && apt-get install -y zlib1g-dev libpq-dev mariadb-client unzip libzip-dev\
  && docker-php-ext-install zip pdo_mysql mysqli \
  && docker-php-ext-enable mysqli

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

WORKDIR /var/www/html

RUN composer global require "laravel/installer"

※ 以前のバージョンでは不要でしたが、今回インストールするcomposerには「libzip-dev」が必要なので一緒にインストールします。

php.ini

PHPの設定ファイルを作成します。

[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

Apacheの設定ファイル

Apacheのポートや、ドキュメントルートなど、最低限の設定を行います。

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/public
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Dockerコンテナの起動

各種ファイルの準備ができたら、次のコマンドを使用してDockerコンテナを起動します。最初は400MB近いファイルがダウンロードされ時間がかかるので、気長に待ちます。

$ docker-compose up -d

Laravelプロジェクトの作成

webのコンテナ にシェルでログインして、Laravelの新規プロジェクトを作成します。

# webコンテナにシェルで入ります
$ docker-compose exec web bash

# 新規のLaravelプロジェクト作成します
$ laravel new

動作確認

ここまでで、WEBとDBのコンテナの作成と、Laravel新規プロジェクトの作成は完了です。作成したコンテナが正常に動作しているか確認していきましょう。

ブラウザでhttp://127.0.0.1/にアクセスして、Laravelプロジェクトが正常に動作しているか確認します。
スクリーンショット 2020-07-24 13.50.42.png

次に、データベース(MariaDB)とAdminerが動作しているか確認します。
ブラウザでhttp://127.0.0.1:8080/にアクセスし、docker-composeで指定したパスワードでログインします。
スクリーンショット 2020-07-24 14.10.11.png

ログインに成功すると、次のような画面が表示されます。
スクリーンショット 2020-07-24 19.10.19.png

まとめ

PHP7.4のLaravel開発環境を作ってみました。デバッグ実行はできませんが、dockerを使えば簡単にPHP+Laravelの環境が作れて便利です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gemfileにデバッグツールpry-byebugを入れてもデバッグできない時の解決方法(回避)

RubyOnRails学習のため、Docker、Gemfile使用

動作の確認をしたいため、
Gemfileにpry-byebugを導入

Gemfile
    group :development do
        ...
        gem 'pry-byebug'
    end

コマンドにて、
docker-compose build
を実行、そのあと、
docker-compose up -d
docker ps
でデバッグするファイルを確認。
しかし、デバッグターゲットとなる xxx_web_1 が表示されない。

解決方法(回避)

Gemfileに
pry-byebugを導入する代わりに、
pry-railsを導入する。

Gemfile
    group :development do
        ...
        gem 'pry-rails'
    end

コマンドにて、
docker-compose build
docker-compose up -d
docker ps
xxx_web_1 が表示されたため、
docker-compose upで一旦起動。そのあと、
docker attach xxx_web_1でデバッグターゲットを設定。

コマンド
    web_1  |
    web_1  |      9: def create
    web_1  |  => 10:   binding.pry
    web_1  |     11: end
    web_1  |

余談

コードにbinding.pryを書いて実行したところ、
ブラウザーで
undefined method `pry' for #Binding:XXXXX
が表示された時も、
pry-railsを導入することで、解決できた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSガチで何もわかってない人がECSでWordPressをデプロイするまで

AWSはネットワークが独学難しく、半ば挫折気味でした。

AWSだと「Hello World!」を出すまでが非常に難しく(VPC、サブネット、ルーティングetc)まずは手を動かしてみるのにいい題材はないだろうか?

...と考えていたところ、ECSでWordPressをデプロイしてみるのが非常に簡単でオススメだということで、実際にやってみました。

必要なもの

dockerコンテナをローカルで立ち上げてみる

1. CLI上でdocker-composeファイル作成

(とりあえずディレクトリ直下にdocker-compose.yml作成いただければOKです)

  • cd path/to/your/directory プロジェクトを作成するディレクトリへ移動してください
  • mkdir {フォルダ名} && cd {フォルダ名} フォルダを作成し、そのディレクトリへ移動します
  • touch docker-compose.yml doccker-composeという複数コンテナからなるサービスを実行するための手順書(のようなもの)を作成します。
  • vi docker-compose.yml
  • i インサートモード起動
  • ▼をコピペ
docker-compose.yml
version: '2'
  services:
    wordpress:
      image: wordpress
      mem_limit: 268435456
      ports:
      - "80:80"
      links:
      - mysql
    mysql:
      image: mysql:5.7.25
      mem_limit: 268435456
      environment:
        MYSQL_ROOT_PASSWORD: password
  • esc インサートモード終了
  • :wqを押してEnter
    これでファイルを保存しviを終了します

2. docker-composeファイルのビルド

  • docker-compose up -d 先ほど作成したファイルがあるディレクトリ直下で実行します
  • docker ps mysql:5.7.25とwordpressというイメージが作成されているのを確認します。
  • ブラウザでhttp://localhostへアクセス 自動的に次のような画面にリダイレクトされると成功です。

スクリーンショット 2020-07-24 16.05.28.png

AWS ECS上でdockerコンテナを実行する

(参考) Homebrewによるecs-cliのインストール

  • パッケージのインストール
    brew install amazon-ecs-cli
  • 初回インストールなのでリージョン/クラスター設定
    ecs-cli configure --region ap-northeast-1 --cluster {好きなクラスター名}
    リージョンは日本を示すap-northeast-1を。
    クラスターとはかなりざっくり言えば、dockerコンテナをひとまとめにした大きな括りです。ここでは「wordpress-example」とかで大丈夫です。

実際にECS上にコンテナをデプロイする

先ほどのdocker-compose.ymlの存在するルートディレクトリから実行します。

  • 新規AWS ECSクラスターを作成する
    ecs-cli up --capability-iam --size 2 --instance-type t2.micro
    インスタンスタイプはお好みですが、最小限のt2.microを選択推奨です。
    --capability-iamは、新規でIAMロールを作成することを示唆します。 (https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cmd-ecs-cli-up.html)
    このコマンドを実行することで、新規CloudFormationスタックが作成されます。
  • 成功したら...
    ecs-cli psこちらのコマンドをどうぞ。
    すると下記のような出力がされるはず。
Name                                            State                                                                               Ports                    TaskDefinition  Health

こちらのPorts欄にある({IPアドレス}->80/tcpの){IPアドレス}をコピペして、ブラウザで開けると、ローカルと同じような画面が出てきます。

スクリーンショット 2020-07-24 16.05.28.png

お疲れ様でした!

学んだことなど

AWSコンソールから、ECSクラスターを作成してみても、いっこうにうまくいかなかったのですが、CLIだとここまで簡単にデプロイできるのか!と思いました。

このデプロイをやるだけでも、AWS全くわかってない勢としては、非常に苦戦しましたので、ぜひ参考にしてみていただけますと!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Spring Batchでcsvを取り込むバッチを作ってみました。

はじめに

おはようございます。先日Springを入門し、SpringBatchで小さいバッチを作ってみました。
皆にお役に立つかと思いますので、共有させていただきます。m(_ _)m

日本語を勉強中ですので間違っていることがあればよろしくお願いします。

それでは始めます。

1.要件定義

csv形式で保存される販売情報をシステムに取り組むバッチを作ります。

実際、ウェブアプリでもいけますが(例えばサイトの画面でファイルを選んで、送信するとcsvを取り組むアプリなど)、SpringBatchを使ってみたいので、この場面バッチを作る必要があるとします。

それではプログラミングのInput、outputから説明してきます。

1.1.(インプット)販売情報のcsvの内容

orders.csv

customer_id,item_id,item_name,item_price,purchase_date
1,1,150000,asus notebook,2020/07/16 8:00:00
1,2,200000,macbook pro 13 inch,2020/07/16 9:00:00
2,2,200000,macbook pro 13 inch,2020/07/16 10:00:00
2,3,250000,macbook pro 15 inch,2020/07/17 10:00:00

ファイルの内容はいつ、どのユーザーがどの商品、いくらで購入したかの情報です。

例えば2行目は、customerの1がitemの1のasus notebookを2020/07/16に15万円で購入したという意味を示します。

1.2.(アウトプット)テーブルの内容

上のcsvをバッチの実行で、インポートした後、該当するテーブルは下記のようになると期待します。

| id | customer_id | item_id | item_name | item_price | purchase_date |
|--:|--:|--:|:--|--:|:--|
| 1 | 1 | 1 | asus notebook | 150000 | 2020/07/16 |
| 2 | 1 | 2 | macbook pro 13 inch | 200000 | 2020/07/16 |
| 3 | 2 | 2 | macbook pro 13 inch | 200000 | 2020/07/17 |
| 4 | 2 | 3 | macbook pro 15 inch | 250000 | 2020/07/17 |

2.準備

自分のホストPCの情報は下記です。ご参考までと思います。

  • OS : MacOS (Macbook Pro)
  • Java
java version "12.0.2" 2019-07-16
Java(TM) SE Runtime Environment (build 12.0.2+10)
Java HotSpot(TM) 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)

IDEについて自分は通常VSCodeを使っていたので、最初はVSCodeでコーディングしようと思いましたが、SpringBootパッケージをインストールしてもjavaオートインポート機能がうまくいけませんでした。。。そのためこの場合VSCodeをやめました。

またIntellJも試しましたが、CommunityバージョンはSpringをサポートしなませんね・・・

という経由で、IDEはEclipseにしました。

3.実装

3.1.初期化

Spring Initialzrのおかげで簡単にボイラプレートを作れました。
https://start.spring.io/

Screen Shot 2020-07-19 at 20.18.53.png

  • プロジェクト:Maven
    • 現在はGradleのほうが流行している気がしますが、個人的な理由でMavenを選びます。
  • 言語:Java
    • 他にはできないため
  • Dependence:
    • SpringBatch:バッチを作りますので、Spring Batchを選びます。
    • Mysql Driver:Mysqlを使いますので、そのドライバーを選びます。
    • SpringDataJPA:よくわかりませんが、MysqlDriverを操作するためのライブラリようです。

選択終わった後に、Generateを押し、「demo.zip」がダウンロードされます。

3.2.DockerでMysqlのデータベースを作成

ホストにはすでにデータベースが使える状態であればこのステップをスキップしてもいいです。

3.2.1.Docker-composeで構築します

場所:

demo/
    ...
    docker-compose.yml
    db/
    ...

demo/docker-compose.yml

version: '3'

services:
  database:
    image: mysql:8.0
    volumes:
      - ./db/dbdata:/var/lib/mysql
    command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-authentication-plugin=mysql_native_password']
    environment:
      MYSQL_DATABASE: demo
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: demo
      MYSQL_PASSWORD: demo
    ports:
        - "33061:3306"

ご覧になる通りにデーターベースの情報は:

  • 初期で作られるデータベース名:demo
  • ユーザー名:demo
  • パスワード:demo

3.2.2.テーブルを作成

これでデータベースが作成できましたが、まだテーブルがないのでバッチから呼び出すとエラーが出ます。そのためテーブルを作ります。

データーベースを起動:

$ docker-compose up -d
$ mysql -u demo -P 33061 -p

ordersというテーブルを作ります

CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id INT(12) NOT NULL,
  item_id INT(12) NOT NULL,
  item_name VARCHAR(50),
  item_price INT(12) NOT NULL,
  purchase_date DATETIME
);

Query OK, 0 rows affected, 3 warnings (0.05 sec)

これでデータベースは大丈夫でした。

3.3.プロジェクトをインポート

3.1からzipが作られました。次はeclipseで解凍したディレクトリをインポートします。

Screen Shot 2020-07-19 at 20.10.45.png

Import > Maven > Existing Maven Project

次はバッチを設計します。

3.4.設計

sample_spring_batch (1).jpg

エントリーポイントから説明していきます。

  • BatchProcessingApplication:アプリのエントリーポイントです。@SpringBootApplicationのAnnotationをつけたことで、自動で同じ階増にあるクラスを読み込むようフレームワークに指定することができます。
  • BatchConfiguration:名前の通りに、バッチの設定はここです。
  • (Job)importOrderJob:バッチにあるJobの一つです。実際のバッチには複数のJobがあるのは一般ですが、今回のプログラムは簡単ですので、このJobしか存在しません。csvを取り込む役をするJobです。
  • (Step)step1():importOrderJobの最初、一つのみの実行ステップです。
  • (ItemReader) reader() :step1のステップ内にあるもっと小さいな単位の最初のプロセスです。csvを取り込む役をします。
  • (ItemProcessor) processor() : ステップ内に、csvを取り込んだ後に、そのデータを処理する部分です。
  • (ItemWriter) writer() : csvのデータがインポート、処理された後に、それをDBに追加する部分です。
  • (Repository) OrderRepository : データを保存するのをサポートするSpringが用意したクラスを継承するクラスです。
  • (Entity) Order : csvの行をモデル化するクラスです。それとDBのテーブルを表現するクラスです。実際この2つの定義は違うクラスに分けたほうがいいですが、今回はcsvの行とテーブルの構成はほぼ一緒ですので、同じクラスにします。

3.5.プログラミング

3.5.1.Entityを作成

設計は上から下まで考えていましたが、コーディングはその逆です。EntityのOrderから始めます。

このクラスはcsvの構成、テーブルの構成を表現しますので、このようになります。

com.example.demo.batchprocessing.Order.java

package com.example.demo.batchprocessing;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="orders")
public class Order {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private Integer customerId;

    private Integer itemId;

    private String itemName;

    private Integer itemPrice;

    private String purchaseDate;

    ....
    // Setter + Getter 
    ...
}

Mysqlのドライバーが認識できるように、@EntityのAnnotationをつけます。

実際テーブルとクラス名は異なりますので、フレームワークがクラスに紐付けるテーブルが認識できるように、@Table(name="orders") をつけます。

3.5.2.レポジトリを作成

SpringではDBにデータを追加するにはEntityだけではまだいけないので、その隙間を満たすレポジトリを作成します。

com.example.demo.batchprocessing.OrderRepository

package com.example.demo.batchprocessing;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends CrudRepository<Order, Integer> {

}

中身にはあまりないです。ordersテーブルでCRUD操作をしたいので、CrudRepositoryを継承します。
Orderのエンティティを操作したい、またOrderのidは形はIntegerなので、合わせて<Order, Integer>を継承する構文に宣言します。

3.5.3.BatchConfigurationを作成

com.example.demo.batchprocessing.BatchConfiguration

package com.example.demo.batchprocessing;

import ....

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    private OrderRepository orderRepository;

    @Bean
    public ItemReader<Order> reader() {
        return new FlatFileItemReaderBuilder<Order>()
            .name("orderItemReader")
            .resource(new ClassPathResource("orders.csv"))
            .delimited()
            .names(new String[] {"CustomerId", "ItemId", "ItemPrice", "ItemName", "PurchaseDate"})
            .fieldSetMapper(new BeanWrapperFieldSetMapper<Order>() {{
                setTargetType(Order.class); 
            }})
            .build();
    }

    @Bean
    public ItemProcessor<Order, Order> processor() {
        return new ItemProcessor<Order, Order>() {

            @Override
            public Order process(final Order order) throws Exception {
                return order;
            }
        };
    }


    @Bean
    public ItemWriter<Order> writer() {
        RepositoryItemWriter<Order> writer = new RepositoryItemWriter<>(); 
        writer.setRepository(orderRepository);
        writer.setMethodName("save");
        return writer;
    }
  • ItemReader reader() : 普段DBから取り込む、ファイルから取り込む、取り込むために複数の既存クラスの使用の選択がありますが、今回はcsvから取り込むなので、それに当てはまるクラスのFlatFileItemReaderを選びます。
    • csvの場所は「orders.csv」であることも指定する
    • カラム名をnames()関数で指定する
    • 読み込んだcsvの行をOrderクラスに格納するように指定する
  • ItemProcessor processor() : csvから読み込んだデータを処理します。今回自分は何も処理せずそのままwirterに引き渡しますが、実際はバリデーション、変換などの処理が書かれることがあるかもしれませんね。

  • ItemWriter writer() : processorから処理終わったデータを受け取って、DBに取り込むように処理する部分です。普段他のファイルにデータを追加、ストリームでデータを送る、などのWriterがあるかもしれませんが、この場合DBにデータを追加したいので、その該当する業務を実現するクラスのRespositoryItemWriterを使います。

次はJobとステップの処理を作成します。

    @Bean
    public Job importOrderJob()
    {
        return jobBuilderFactory.get("importOrderJob")
            .incrementer(new RunIdIncrementer())
            .listener(new JobCompletionNotificationListener())
            .flow(step1())
            .end()
            .build();
    }

    @Bean
    public Step step1() {
      return stepBuilderFactory.get("step1")
        .<Order, Order> chunk(10)
        .reader(reader())
        .processor(processor())
        .writer(writer())
        .build();
    }
  • 下記の設定でimportOrderJobを作成します
    • Jobが実行完了というイベントを常に聞く、あればアクションするというListenerを設定:listener(new JobCompletionNotificationListener())(このクラスは後で説明します)
    • step1の実行を呼び出す
  • ステップのstep1を作成します
    • 一回に10個を処理するというチャンクを宣言する
    • reader()、processor()、writer()が順番に実行するようにそれぞれ宣言する

3.5.4.JobCompletionNotificationListenerを作成

Job実行完了のイベントが起きる時に起動されるアクションを設定します。

com.example.demo.batchprocessing.JobCompletionNotificationListener

package com.example.demo.batchprocessing;

import ....

@Component
public class JobCompletionNotificationListener extends JobExecutionListenerSupport {

    private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);

    @Override
    public void afterJob(JobExecution jobExecution) {
        if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
            log.info("!!! JOB FINISHED ");
        }
    }
}

Jobのイベントごとにアクションをトリガーするよう、その役をするJobExecutionListenerSupportクラスを継承します。

他のイベントもあるらしいけど、実行完了のイベントのみ利用したいので、afterJob関数をオーバーライドします。
ただログに出力するようにする処理があります。

3.5.5.BatchProcessingApplicationを作成

最後に、アプリのエントリーポイントを作成します。

com.example.demo.batchprocessing.BatchProcessingApplication

package com.example.demo.batchprocessing;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BatchProcessingApplication {
    public static void main(String[] args) throws Exception {
        System.exit(SpringApplication.exit(
            SpringApplication.run(BatchProcessingApplication.class, args))
        );
    }
}

単にJavaのみ作成すると、複数のクラスを呼び出す、それを連携するなどの処理が必要になりますが、Springのおかげで数行だけ書いても結構です。

要は@SpringBootApplicationをクラスにつけることです。
そのため、自動的に同じパッケージの配下にあるクラスを宣言しなくても、ロードすることができます。

SpringApplication.run(BatchProcessingApplication.class, args))

を呼び出すだけでプログラムが実行できます。

3.5.6.要らないクラス、処理を廃棄

SpringInitializrから作成させるプロジェクトにはデフォルト処理やクラスがあります。

今回エントリーポイントを新規に作成するので、既存のエントリーポイントを削除します。

$ rm src/main/java/com/example/demo/DemoApplication.java
$ rm src/main/java/com/example/demo/DemoApplicationTests.java

また簡単にテストコードも書きます。

com.example.demo.batchprocessing.test.DemoApplicationTests.java

package com.example.demo.batchprocessing.test;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class BatchProcessingTests {

   @Test
   void contextLoads() {
   }

}

プログラミングはこれで以上です!

4.実行

4.1.データベースを起動

dockerで起動します

$ docker-compose up -d

4.2.コマンドでバッチを実行する

IDE経由で実行してもいいですが、自分が好む方法のコマンドラインで実行したいと思います。

$ ./mvnw spring-boot:run

最初に実行する時にライブラリをインストールする時間がかかりますが、2回めからは早いです。

実行結果はこんなイメージです。

Screen Shot 2020-07-23 at 0.10.28.png

データベースでデータがインサートされるかを確認します。

$ mysql -h 0.0.0.0 -u demo -P 33061 -p demo

$ mysql> select * from orders;
+----+-------------+---------+---------------------+------------+---------------------+
| id | customer_id | item_id | item_name           | item_price | purchase_date       |
+----+-------------+---------+---------------------+------------+---------------------+
| 85 |           1 |       1 | asus notebook       |   150000 | 2020-07-16 08:00:00 |
| 86 |           1 |       2 | macbook pro 13 inch |   200000 | 2020-07-16 09:00:00 |
| 87 |           2 |       2 | macbook pro 13 inch |   200000 | 2020-07-16 10:00:00 |
| 88 |           2 |       3 | macbook pro 15 inch |   250000 | 2020-07-17 10:00:00 |
+----+-------------+---------+---------------------+------------+---------------------+
4 rows in set (0.00 sec)    

csvの内容通りにデータが作成されたので、バッチ作成はとりあえずOKだと思います。

5.終わりに

SpringBatchを入門する経由を共有させていただいました。
こかからSpringBatchを学びたい方々になにかお役に立てば幸いです。

本文にまだ説明が足りないところがあれば失礼します。
https://github.com/mytv1/sample-spring-batch

プロジェクトの処理全部は上のレポをご参考になればと思います。

6.参考

https://spring.io/guides/gs/batch-processing

https://spring.io/guides/gs/accessing-data-mysql

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

svelteの開発環境の作り方

開発環境

  • macOS Catalina
  • docker -v @19.03.8

開発環境の作り方

svelteプロジェクト作成

npx degit sveltejs/template svelte-spa
cd svelte-spa

Dockerからlocalhostにつなげるための設定

package.json
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
-   "start": "sirv public"
+   "start": "sirv public build --host 0.0.0.0"
  },

Dockerfileを作成

touch Dockerfile
Dockerfile
FROM node:12-alpine
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 5000
ENV HOST=0.0.0.0
CMD [ "npm", "start" ]

Docker起動を確認

docker build -t svelte/svelte-spa .
docker run -p 5000:5000 svelte/svelte-spa

http://0.0.0.0:5000/にアクセスしてsvelteのHelloWorldが開けることを確認

image.png

やった!

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Windows10でDocker環境構築】python3 + nginx + Django + PostgreSQL

Windows10でDockerを使用してDjango環境を構築

PCのスペック

項目 スペック
CPU COREi7
Memory 8G
Storage SSD

今のところ、普通に動作し開発できています。

Editor

VSCodeを使用
フォルダやファイル作成からTerminalとしてコマンド入力も行っています。

準備

1.Dockerを使用するにはHpyer-Vを有効化する必要があるため、下記の対応が必要です。
  • BIOSの設定変更:
     Intel VTをEnabledにする。
  • OS:
     Windows10 Pro 64bit(Hpyer-Vを有効化できるのはWindows10 Proのみのため)
2.Python3.8.2(64bit版)のインストール

Pipenvを使用しますので、PCにPythonをインストールします。
意図的に64bit版をダウンロードしないと、34bit版がダウンロードされますの注意が必要です。

https://www.python.org/downloads/windows/

から、

Python 3.8.2 - Feb. 24, 2020
->Download Windows x86-64 executable installer

を選択してダウンロードする必要があります。

3.環境変数の設定

PathにPythonのインストール先ディレクトリを設定してください。
Pythonのデフォルトインストール先はProgram Files配下ではなく、

C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38

になります。

バージョン

インストールしたソフトウェアのバージョン

  • Docker:2.3.0.3
  • Docker-compose:1.25.5
  • ubunts:20.04
  • python:3.8.2
  • Django:3.0.6
  • gunicorn:20.0.4
  • psycopg2:2.8.5
  • PostgeSQL:12.3
  • nginx:1.17.10

dockerインストール

下記のサイトなどからDocker Desktopをダウンロードしてインストール

https://www.docker.com/get-started
https://hub.docker.com/editions/community/docker-ce-desktop-windows/

ディレクトリ構成

test
├── app
│   ├── .venv ※配下にフォルダがあります
│   ├── mysite
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── manage.py
│   ├── Dockerfile
│   ├── Pipfile
│   └── Pipfile.lock
├── db
│   ├── dbdata
│   ├── initdb.d
│   └── Dockerfile
│       └── init.sql
├── nginx
│   └── default.conf
│   ├── Dockerfile
│   └── nginx.conf
└── docker-compose.yml

構成

構成は
 Clien<-(Port:80)->nginx<-(Proxy/Port:8000)->Gunicorn<-->Django<-(Port:5423)->PostgreSQL
となります。

構築していきます

1.PipenvによるPython仮想環境の構築

Pythonということもあり、Pipenvを利用します。

1-1.Pipfileを作成
.\test\app\Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
django = "==3.0.6"
gunicorn = "==20.0.4"
psycopg2 = "==2.8.5"

[requires]
python_version = "3.8.2"
1-2.Python仮想環境の構築

.\test\appに移動して、コマンドを実行します。
正常に構築が完了していれば指定したバージョンのPackageがインストールされています。
[]は接続先環境になります。

[Powershell]>pip install pipenv
[Powershell]>pipenv install
[Powershell]>pipenv shell
[pipenv]>python -V
Python 3.8.2
[pipenv]>pip list
Package    Version
---------- -------
asgiref    3.2.10
Django     3.0.6
gunicorn   20.0.4
pip        20.1.1
psycopg2   2.8.5
pytz       2020.1
setuptools 49.2.0
sqlparse   0.3.1
wheel      0.34.2

(1)VSCodeはTerminalウィンドウの右上に接続環境が表示されます。pipenvと表示されていればPythonの仮想環境に入っています。
(2)pipenv installが完了する.\test\app配下に
  ・.envフォルダ
  ・Pipfile.lockファイル
 が作成されます。

1-3.Djangoの動作確認

Djangoプロジェクトを作成します。

[pipenv]>django-admin startproject mysite .

プロジェクトの作成が完了すると.\test\app配下に
 ・mysiteフォルダ
 ・manage.pyファイル
が作成されます。

4.Djangoプロジェクトの確認

Djangoを立ち上げます。

[pipenv]>python manage.py runserver localhost:8000

ブラウザから http://localost:8000 にアクセスし

django.png

が表示されれば正常に動作していることになります。
確認できればexitし、VSCodeのDockerから該当のCONTAINERSを削除。

2.Django用Dockerファイルの作成

フォルダ.\test\app配下にDockerファイルを作成します。
.\test\app\Dockerfile
FROM ubuntu:20.04

SHELL ["/bin/bash", "-c"]

RUN apt-get update -y \
    && apt-get upgrade -y \
    && apt-get install -y python3.8 python3.8-dev \
    && source ~/.bashrc \
    && apt-get -y install vim

WORKDIR /usr/src/test/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get install -y curl \
    && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
    && apt-get install -y python3.8-distutils \
    && python3.8 get-pip.py \
    && pip install -U pip \
    && apt-get install -y build-essential libssl-dev libffi-dev python-dev python3-dev libpq-dev

RUN pip install pipenv

COPY Pipfile ./

RUN pipenv install --system --skip-lock \
    && pip uninstall -y pipenv virtualenv-clone virtualenv

COPY . /usr/src/test/app/

3.PostgreSQL用Dockerファイルの作成

3-1.フォルダ.\testに移動して.\test\dbフォルダを作成し、.\test\dbの配下に下記のフォルダを作成します。

 ・.\test/db\dbdata
 ・.\test\db\initdb.d

3-2.フォルダ.\test\Dockerfileを作成します。
.\test\db\Dockerfile
FROM postgres:12.3
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.utf8
3-3.初期設定が必要な場合、.\test\db\initdb.d配下にSQLを配置します。
3-4.フォルダ.\test\app\mysite\setting.pyにPostgreSQLのDATABASE設定を記載します。
.\test\app\mysite\setting.py
---(中略)----

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD' : 'postgres'
    }
}

---(中略)----

4.nginx用Dockerファイルの作成

4-1.フォルダ.\testに移動して.\test\nginxフォルダを作成します。
4-2.フォルダ.\test\nginx配下にDockerfileファイルを作成します。
.\test\nginx\Dockerfile
FROM nginx:1.17.10
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
COPY default.conf /etc/nginx/
RUN ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
4-3.フォルダ.\test\nginx配下にnginx.confファイル、default.confファイルを作成します。

nginx経由でDjangoサーバーにアクセスするので、proxyの設定をします。

.\test\nginx\nginx.conf
upstream mysite {
    server app:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://mysite;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
    }
}
.\test\nginx\default.conf
user  nginx;
worker_processes  1;
http {
    log_format main '$remote_addr - $remote_user [$time_local]  "$status"' 
                    '"$request" $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
}

5.docker-compose.ymlファイルの作成

フォルダ.\testに移動して直下にdocker-compose.ymlファイルを作成します。
.\test\docker-compose.yml
version: "3.7"
services:
  web:
    container_name: nginx
    build: ./nginx
    ports:
      - 80:80
    depends_on:
      - app
    restart: always

  app:
    container_name: devapp
    build: ./app
    command: gunicorn mysite.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./app:/usr/src/test/app/
    ports:
      - 8000:8000
    depends_on:
      - db
    restart: always

  db:
    container_name: devdb
    build: ./db
    volumes:
      - ./db/dbdata:/var/lib/postgresql
    ports:
      - 5432:5432
    environment: 
      POSTGRES_PASSWORD: 'postgres'
    restart: always

volumes:
    dbdata:

6.動作確認

6.1.フォルダ.\testに移動し、仮想環境を立ち上げます。
[Powershell]>docker-compose up -d --build
6-2.http://localhost にアクセスし、

localhost.png

が表示されれば完了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu 20.04 LTS server setting memo

既存サーバ(Ubuntu 16.04 LTS)からの移行を行ったときのメモ

  • 設定する構成:network port mapping
ext in service
80 80 docker:gitlab
443 443 docker:gitlab
30080 80 docker:kerberos
40443 443 docker:nextcloud
40080 80 docker:nextcloud
50000 - webmin

Server Nmae: [Hogehoge.com]

まずは環境設定

Let's Encrypt Setting

  • インストール

    $> apt install certbot
    $> apt update
    $> apt upgrade
    
  • BackupとRestore

    $>tar cvzf letsencrypt_backup.tar.gz /etc/letsencrypt
    
  • 更新する

    $> certbot renew --standalone
    

Webmin Setting

  • インストール

    $> apt -y install python apt-show-versions libapt-pkg-perl libauthen-pam-perl libio-pty-perl libnet-ssleay-perl unzip
    $> curl -L -O http://www.webmin.com/download/deb/webmin-current.deb
    $> systemctl restart smbd
    $> dpkg -i webmin-current.deb
    $> systemctl restart webmin
    
  • Let's Encrypt設定

    Webmin -> Webmin Configuration -> SSL Encryption -> SSL Setings -> 
     Private Key file : /etc/letsencrypt/live/Hogehoge.com/privkey.pem
     Certificate file : /etc/letsencrypt/live/Hogehoge.com/fullchain.pem
    
  • ポート変更

    Webmin -> Webmin Configuration -> Ports and Addresses -> 
     Listen on port : 10000 -> 50000
    
  • アクセスして確認
    https://Hogehoge.com:50000/

Docker Setting

前提:インストールオプションでDockerはインストール済み

  • Create directory

    $> mkdir docker
    $> mkdir docker/gitlab
    $> mkdir docker/nextcloud
    $> mkdir docker/kerberos_usb
    
  • CUI 管理ツール : Lazydocker インストール

    $> curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash
    
  • アクセスして確認

    $> lazydocker
    

Gitlab Setting @ docker

  • ディレクトリ作成と認証ファイルのシンボリックリンク

    $> cd gitlab
    $> ln -s /etc/letsencrypt letsencrypt
    
  • docker-compose.yaml

    version: '3'
    services:
    gitlab:
      container_name: gitlabC0
      image: 'gitlab/gitlab-ce:12.5.3-ce.0'
      restart: always
      hostname: 'hogehoge.com'
      environment:
        GITLAB_OMNIBUS_CONFIG: |
          external_url 'https://hogehoge.com'
          gitlab_rails['time_zone'] = 'Asia/Tokyo'
          nginx['ssl_certificate'] = "/etc/letsencrypt/live/hogehoge.com/cert.pem"
          nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/hogehoge.com/privkey.pem"
    ports:
    - "80:80"
    - "443:443"
    volumes:
    - ${PWD}/letsencrypt:/etc/letsencrypt
    - ${PWD}/config:/etc/gitlab
    - ${PWD}/logs:/var/log/gitlab
    - ${PWD}/data:/var/opt/gitlab
    

original環境のBackup。original環境とrestore先は同じバージョンにする必要がある

  $> docker exec -it gitlabC0 bash
  $> gitlab-rake gitlab:backup:create
      -> /var/opt/gitlab/backup
      日付_gitlab_backup.tar
  
  • 設定ファイルのBackup

    $> tar -zcvf ~/$(date "+%s_%Y_%m_%d_etc_gitlab.tar.gz") -C /etc gitlab
      -> 日付_etc_gitlab.tar.gz
    
  • dockerのマウントしているVolumeにコピー

    $> cp 1593628898_2020_07_02_12.5.3_gitlab_backup.tar docker/gitlab/data/backups/
    
  • Restore
    一度新規でGitlabを立ち上げる。初期化まで多少の時間がかかる。
    gitlabは止めずに実行する。

    $> docker exec -it gitlabC0 bash
    

docker/configの内容を設定ファイルで保存した内容で上書き

  $> gitlab-rake gitlab:backup:restore BACKUP=1593628898_2020_07_02_12.5.3
    Unpacking backup ... done
    Before restoring the database, we will remove all existing
    tables to avoid future upgrade problems. Be aware that if you have
    custom tables in the GitLab database these tables and all data will be
    removed.
    ::
    Do you want to continue (yes/no)? yes
    Removing all tables. Press Ctrl-C within 5 seconds to abort
    2020-07-24 02:03:52 +0000 -- Cleaning the database ... 
    ::
    This task will now rebuild the authorized_keys file.
    You will lose any data stored in the authorized_keys file.
    Do you want to continue (yes/no)? yes
  
  • 再構築と再起動
    $> gitlab-ctl reconfigure
    $> gitlab-ctl restart
    

Nextcloud Setting @ docker

  • ディレクトリ作成と認証ファイルのシンボリックリンク

    $> cd nextcloud
    $> docker network create lb_web
    $> ln -s /etc/letsencrypt letsencrypt
    $> touch docker-compose.yaml
    $> touch nginx.conf
    
  • docker-compose.yaml

    version: '2'
     networks:
       lb_web:
       external: true
    back:
      driver: bridge
    services:
    web:
      image: nginx
      volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./letsencrypt:/etc/letsencrypt:ro
      links:
      - app
      volumes_from:
      - app
      environment:
      - VIRTUAL_HOST
      networks:
      - back
      - lb_web
      ports:
      - 40080:80
      - 40443:443
    app:
      image: nextcloud:fpm
      links:
      - db
      volumes:
      - ./data/apps:/var/www/html/apps
      - ./data/config:/var/www/html/config
      - ./data/data:/var/www/html/data
      networks:
      - back
    db:
      image: mysql
      volumes:
      - ./mysql/runtime:/var/lib/mysql
      environment:
        MYSQL_ROOT_PASSWORD: fmrx98v
      networks:
      - back
    cron:
      image: nextcloud:fpm
      links:
      - db
      volumes_from:
      - app
      user: www-data
      entrypoint: |
        bash -c 'bash -s <<EOF
        trap "break;exit" SIGHUP SIGINT SIGTERM
        while /bin/true; do
          /usr/local/bin/php /var/www/html/cron.php
          sleep 900
        done
        EOF'
      networks:
      - back

  • nginx.conf

    user www-data;
    events {
    worker_connections 768;
    }
    http {
    upstream backend {
        server app:9000;
    }
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/hogehoge.com/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/hogehoge.com/privkey.pem;
    
    Add headers to serve security related headers
    
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    
    root /var/www/html;
    
    location = /robots.txt {
      allow all;
      log_not_found off;
      access_log off;
    }
    
    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }
    
    client_max_body_size 1G;
    fastcgi_buffers 64 4K;
    
    gzip off;
    
    index index.php;
    error_page 403 /core/templates/403.php;
    error_page 404 /core/templates/404.php;
    
    location / {
        rewrite ^ /index.php$uri;
    }
    
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }
    
    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34]).php(?:$|/) {
        include fastcgi_params;
        fastcgi_split_path_info ^(.+.php)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass backend;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }
    
    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }
    
    Adding the cache control header for js and css files
    
    Make sure it is BELOW the PHP block
    
    location ~* .(?:css|js)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=7200";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000;
        #  includeSubDomains; preload;";
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don't log access to assets
        access_log off;
    }
    location ~* .(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        access_log off;
    }
    }
    }
    
  • アクセスして確認
    https://hogehoge.com:40443/

    • ユーザ名: 任意のユーザ名
    • パスワード: 任意のパスワード
    • データベースを設定してください: MySQL/MariaDBを選択
    • データベースのユーザ名:root
    • データベースのパスワード: docker-compose.yamlに記入したもの
    • データベース名: nextcloud
    • データベースのホスト名: db

Timeoutになっても問題ない。十分待つこと。PC Spec次第であるが、完了まで多少の時間がかかる。
完了前にアクセスすると初期画面のままなので、そのまま進めると多重処理でエラーとなる。

Kerberos.io Setting @ docker

  • ディレクトリ作成と認証ファイルのシンボリックリンク

    $> cd kerberos_usb
    $> touch docker-compose.yaml
    
  • docker-compose.yaml

    version: '2'
    services:
    app_krb:
      image: kerberos/kerberos
      devices:
      - /dev/video0:/dev/video0:mwr
      environment:
      - VIRTUAL_HOST
      - TZ=Asia/Tokyo
      ports:
      - 30080:80
      - 8889:8889
      volumes:
      - ./kerberosio:/etc/opt/kerberosio
    
  • アクセスして確認
    http://hogehoge.com:3380/

  • USB UVCカメラ設定
    LoginしてConfiguration->Machinery->Advanced設定->Capture->USBcamera

  • ストリーム確認
    http://user:pass@hogehoge.com:8889/mjpeg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-composeでコンテナの初回起動時に特定の処理を行う方法

TL; DR

docker-composeでコンテナの初回起動時に特定の処理を行う方法を簡潔にまとめました。

  1. 初回起動判定付きのシェルスクリプトを作成する
  2. docker inspect コマンドでベースイメージのENTRYPOINTとCMDを調べる
  3. シェルスクリプト → ENTRYPOINT → CMDの順で実行するように設定する

経緯

Dockerfile内でコンテナ初回起動時のみ特定の処理を行うように設定する場合、初回起動判定を仕込んだdocker-entrypoint.shをENTRYPOINTに指定するのが一般的ですが、docker-composeの設定だけでコンテナ初回起動時に処理を挟みたいときにはどうしたら良いのか気になったので試してみました。

※ docker-entrypoint.shについてはこちらの記事の解説が分かりやすいです。
dockerで初回起動時のみ特定の処理を行うヘルパースクリプト(docker-entrypoint.sh)

サンプル

ディレクトリ構成

tree
.
├── db
│   ├── init
│   │   └── 01_create_users.sql
│   └── tmp
│       └── container-init.sh
└── docker-compose.yml

初回起動判定付きのシェルスクリプト

container-init.sh
if [ ! -e '/check' ]; then
    touch /check
    # 初回起動時に実行させたいコマンドをここに書く
    echo "セットアップ"
else
    # 2回目以降
    echo "セットアップ済"
fi

docker inspect

ベースイメージがローカルに無い場合は事前に取得してから docker inspect でENTRYPOINTとCMDを確認します。

$ docker pull mysql:5.7
5.7: Pulling from library/mysql
6ec8c9369e08: Pull complete
177e5de89054: Pull complete
ab6ccb86eb40: Pull complete
e1ee78841235: Pull complete
09cd86ccee56: Pull complete
78bea0594a44: Pull complete
caf5f529ae89: Pull complete
4e54a8bcf566: Pull complete
50c21ba6527b: Pull complete
68e74bb27b39: Pull complete
5f13eadfe747: Pull complete
Digest: sha256:97869b42772dac5b767f4e4692434fbd5e6b86bcb8695d4feafb52b59fe9ae24
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

$ docker inspect mysql:5.7 --format='{{.Config.Entrypoint}}'
[docker-entrypoint.sh]

$ docker inspect mysql:5.7 --format='{{.Config.Cmd}}'
[mysqld]

docker-compose

docker-compose.ymlでentrypointタグで上書きすると、DockerfileのENTRYPOINTとCMDが無視されるので、まとめて指定します。

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: sample
    ports:
      - 3306:3306
    volumes:
      - ./db/tmp:/tmp # container-init.shをコンテナから参照できるようにするため
      - ./db/init:/docker-entrypoint-initdb.d
      - ./db/data:/var/lib/mysql
    container_name: sample-db
    entrypoint: >
      sh -c "
        sh /tmp/container-init.sh &&
        docker-entrypoint.sh mysqld \
          --character-set-server=utf8mb4 \
          --collation-server=utf8mb4_unicode_ci
      "
    # commandタグで指定していたものはentrypointタグでまとめて指定する
    # command: >
    #   --character-set-server=utf8mb4
    #   --collation-server=utf8mb4_unicode_ci

リポジトリ

https://github.com/OskaMathis/docker-compose-sample

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Re:Dashのインストール(Docker)

DockerでBIツールのRe:Dashをインストールした際のメモ。
MetabaseやSupersetが競合。
SQL必須と使い勝手はイマイチだが、接続先候補が多いのが特徴。

公式サイト
https://redash.io

Plotly Dashと間違えて入れたのは内緒です……。

1. インストール手順

docker-compose.yml

version: '2'
x-redash-service: &redash-service
  image: redash/redash:latest
  depends_on:
    - postgres
    - redis
  env_file: redash.env
  restart: always
services:
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
  scheduler:
    <<: *redash-service
    command: scheduler
    environment:
      QUEUES: "celery"
      WORKERS_COUNT: 1
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
  redis:
    image: redis:latest
    restart: always
  postgres:
    image: postgres:latest
    env_file: redash.env
    restart: always
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always

同一フォルダに環境設定ファイルを作成する。
redash.env

REDASH_HOST=http://localhost/redash
PYTHONUNBUFFERED=0
REDASH_LOG_LEVEL=INFO
REDASH_REDIS_URL=redis://redis:6379/0
POSTGRES_DB= redash
POSTGRES_USER= redash
POSTGRES_PASSWORD= hogehoge
REDASH_COOKIE_SECRET=redash-selfhosted
REDASH_SECRET_KEY=redash-selfhosted
REDASH_DATABASE_URL=postgresql://redash:hogehoge@postgres/postgres

REDASH_DATABASE_URLに
「POSTGRES_USERの値:POSTGRES_PASSWORD値@postgres/postgres」
を入れるのがポイント。

※ パスワード要らないという外人のサイトに騙されるなど……。

2. 起動とアクセス

docker-compose.ymlのあるフォルダにて下記コマンドで起動。

docker-compose run --rm server create_db
docker-compose up -d

REDASH_HOSTの設定(http://localhost/redash
でアクセスできる。

3. 削除

削除はdocker-compose.ymlのフォルダで下記を実施。

docker-compose down --rmi all --volumes

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者がDockerで開発環境構築してみた(Rails&MySQL)

はじめに

現在、就職活動中のプログラミング初学者です。
開発環境にDockerを取り入れる為、いろいろ勉強して自分用のメモとしてまとめておりましたが、折角なら同じ初学者の方の役に立てればと思い投稿させて頂きます。既に多くの方がDockerの環境構築に関する記事を書かれており、そういった記事を参考にさせて頂きながら、メモとしてまとめていましたので、内容はそんなに目新しものではありません。予めご了承ください。また、誤った表現などがありましたらご指摘頂けると幸いです。

開発環境

  • Ruby 2.6.3
  • Rails 5.2.3
  • MySQL 5.7
  • MacOS 10.15.5

前提条件

  • Dockerhubのアカウントを作成している。
  • Docker for Macをインストールしている。
  • Dockerの基礎はある程度抑えている。

Dockerの基本的なことはこちらの記事が参考になります。
いまさらだけどDockerに入門したので分かりやすくまとめてみた

対象読者

今回は開発環境を構築することを目標とする為、Dockerに関する基礎的な部分はある程度抑えている方とします。

Railsの開発環境構築

DockerでRailsの開発環境を構築するには以下のファイルが必要になります。

  • Dockerfile
  • Gemfile
  • Gemfile.lock
  • docker-compose.yml

1.作成するアプリ名のディレクトリを作成する。

まずは、上記のファイルを作成するディレクトリを作成します。

#ターミナル
$ mkdir my-app

2.作成したディレクトリに移動する。

$ cd my-app

3.Dockerfileを作成する。

1.で作成したディレクトリ内にDockerfileを作成します。

$ touch Dockerfile

Dockerfileとは?

Dockerでは、dockerhubで公開されているimageを元にコンテナを起動することができるが、必要なパッケージや各種の設定を含んだDocker imageを自分で作成して使用したい場合が出てくる。その場合にDockerfileを用意して、それを元にDocker imageを作成することができる。
Dockerfileにはベースのimageに対して実行する内容を記述する。

4.Dockerfileに記述する。

Dockerfile
# ベースイメージ 今回はrubyのimage。
FROM ruby:2.6.3

# 必要なパッケージのインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs           

# 作業ディレクトリの作成、設定
RUN mkdir /my-app

#作業ディレクトリを指定している
WORKDIR /my-app

# ホスト側(ローカル)のGemfileを追加する(ローカルのGemfileは別途事前に作成しておく)
COPY ./Gemfile /my-app/Gemfile
COPY ./Gemfile.lock /my-app/Gemfile.lock

# Gemfileのbundle install
RUN bundle install
COPY . /my-app

5.Gemfileを作成する。

$ touch Gemfile

6.Gemfileに記述する。

Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.3'

7.空のGemfile.lockを作成する。

$ touch Gemfile.lock

8.docker-compose.ymlを作成する。

$ touch docker-compose.yml

Docker Composeとは?

Dockerでは1つのコンテナには、1つのアプリケーションのみを入れておき、複数のコンテナを組み合わせてサービスを構築するという方法が推奨されている。
Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Docker imageのbuildや各コンテナの起動・停止などをより簡単に行えるようにするツール。

docker-compose.ymlとは?

Docker Composeを使用する際に必要となるファイルのこと。

docker-compose.ymlには以下の内容を定義します。

  • Docker imageをbuildするための情報(使用するDockerfile、image名など)
  • コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
  • 使用するDockerネットワーク など

9.docker-compose.ymlに記述する。

docker-compose.yml
version: '3' # バージョンを指定
services:
  db: # データベースサーバ用のコンテナの設定を記述
    image: mysql:5.7 # コンテナで使用するイメージ名を記述
    environment:
      MYSQL_ROOT_PASSWORD: password # 任意のパスワードを設定
      MYSQL_DATABASE: root # 任意のデータベース名を設定
    ports:
      - "3306:3306" # ホストの3306ポートとコンテナの3306ポートを接続する。
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql #ホストの./db/mysql/volumesをコンテナ内の/var/lib/mysqlにマウントする。Dockerのコンテナと、ローカルを同期している。コンテナを削除してもデータは永続化する。

  web: # アプリケーションサーバ用のコンテナの設定を記述
    build: . # docker-compose.ymlと同じ階層にあるDockerfileを使ってimageをbuildするための記述
    command: bundle exec rails s -p 3000 -b '0.0.0.0' # コンテナ立ち上げ時に起動するコマンド。railsを実行する。

    volumes:
      - .:/my-app # 作業ディレクトリをコンテナ内の/my-appにマウントする。
    ports:
      - "3000:3000" # ホストの3000ポートとコンテナの3000ポートを接続する。
    depends_on:
      - db # 依存関係を表している。dbが起動してからwebが起動するという意味。

10.コンテナを起動し、コンテナ内でrails newを実行する。

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

runコマンドは、imageの構築から、コンテナの構築・起動まで行います。
また、runコマンドを介して引数で指定したサービスのコンテナ内でコマンドを実行できます。つまり、ここでは生成されたコンテナ内でrails newを行っています。
--forceオプションはファイルが存在する場合に上書きで作成するためのオプション。
--database=mysqlオプションは使用するデータベースの指定をするためのオプション。
--skip-bundleオプションはbundle installをスキップするためのオプション。

11.database.ymlを修正する。

rails newで作成されたデータベースの接続設定ファイルにはホスト名とパスワードが設定されていません。railsアプリケーションがデータベースに接続できるようにするため、database.ymlを修正します。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password # docker-compose.ymlのMYSQL_ROOT_PASSWORD
  host: db # docker-compose.ymlのservice名

12.buildを実行する。

$ docker-compose build

ここでbuildを実行する理由は10.で実行したコマンドによりGemfileの内容が書き換わっている為です。

13.Dockerを起動する。

$ docker-compose up -d # docker-compose.ymlを参照してコンテナが一斉起動する。

注意点としてここで実行するdocker-composeコマンドはdocker-compose.ymlを元に実行が進むので、docker-compose.ymlがあるディレクトリ上で実行する必要があります。

14.データベースを作成する。

docker-compose run webをコマンドの先頭につけることでコンテナ内でコマンドを実行できるので、

$ docker-compose run web rails db:create

を実行すれば、データベースが作成できます。

要は、docker-compose run webに続けていつものローカルで開発している時のコマンドが使えます。

では、localhost:3000に接続してみましょう。

以下の画面が表示されれば完了です。

gemを入れてbundle installしてみる。

開発環境が整ったので試しにgemを入れてbundle installしてみます。

Gemfile
gem 'devise'
$ docker-compose run web bundle install

そして、

$ docker-compose run web rails g devise:install

しかし以下のようなエラーが出ました。

Could not find bcrypt-3.1.15 in any of the sources
Run `bundle install` to install missing gems.

bundle installしたはずなのに。。。
これは12.のところと同じ現象です。つまり、ローカルで書き換えたGemfileがコンテナ内のGemfileに反映されていない。ここでは再度、docker-compose buildを行う必要があります。理由はDockerfileを見れば分かります。

Dockerfile
COPY ./Gemfile /my-app/Gemfile
COPY ./Gemfile.lock /my-app/Gemfile.lock

Dockerfile内でimageをbuildする際にローカル側のGemfileをコンテナ側にコピーしていました。ですから、現状ローカルのGemfileの変更はコンテナのGemfileには反映されていない訳です。これを反映させる為に、再度docker-compose buildを行う(imageをbuildし直す)必要があるという訳です。
では、再度docker-compose buildを実行します。

$ docker-compose build

もう一度、エラーが出たコマンドを試します。

$ docker-compose run web rails g devise:install

今度は上手く行きました。

しかし、gemを入れるたびに毎回docker-compose buildするのは面倒臭い。。。

という訳で、毎回docker-compose buildをしなくてもいいようにこちらの記事を参考にさせてもらい、docker-compose.ymlを編集します。
docker-composeでRailsのGemを更新する時、docker buildするのを回避したい

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql

  web:
    build: . 
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/my-app
      - gem_data:/usr/local/bundle # ローカルのgem_dataをコンテナ内の/usr/local/bundleにマウントする。
    ports:
      - "3000:3000"
    depends_on:
      - db

volumes: # 上記のvolumesのgem_dataはローカルのものを使うことを指定している。
  gem_data:

これで、gemをインストールするたびにdocker-compose buildをしなくてもよくなりました。

binding.pryをしたい時

docker-compose.ymlに以下を記述します。

docker-compose.yml
web:
  tty: true
  stdin_open: true

SequelProでデータベースを可視化する。

私はローカルで開発を行う際、SequelProを使用してデータベースを可視化していましたが、コンテナの仮想環境下では現状SequelProでデータベースを可視化することはできません。
docker-compose.ymlを以下の様に書き換えSequelProでデータベースを可視化できるよう設定していきます。

docker-compose.yml
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306" # ホストの4306ポートをコンテナ内の3306ポートに接続するよう書き換える。
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql

次に、sequelpro起動時のモーダル内のタブを標準タブに切り替え、下記の通りに入力します。

名前: defaultのまま
ホスト: 127.0.0.1    # 自分自身を表すIPアドレス
ユーザー名: root    # database.ymlに記載のユーザー名
パスワード: password  # database.ymlに記載のパスワード
データベース: 空欄のまま
ポート: 4306      # docker-compose.ymlに記載したlocal側のports番号

これでdocker環境下でもデータベースが可視化できるようになります。

参考記事・参考動画

今回Dockerを学習するにあたり、多くの方の記事を参考にさせて頂きました。
ありがとうございました。
docker-compose コマンドまとめ
docker-compose up とか build とか start とかの違いを理解できていなかったのでまとめてみた。
既存のRailsアプリをDockerコンテナで動かす方法+sequel proによるDBコンテナ可視化
Dockerを使用したRails開発①(環境構築)
【rails環境構築】docker + rails + mysql で環境構築(初心者でも30分で完了!)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

isucon9 の portal を Amazon Linux2 で動かすメモ

MEMO: 必要あれば ports を適宜変更すること

sudo yum -y update
sudo timedatectl set-timezone Asia/Tokyo
sudo yum -y install docker
sudo systemctl start docker
sudo systemctl enable docker

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

sudo yum -y install git

sudo reboot

git clone git@github.com:chibiegg/isucon9-portal.git
cd isucon9-portal

docker-compose build
docker-compose up

docker-compose exec discard_forever python manage.py manufacture -t 300
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

nginxにモジュールを追加できるDockerfile

docker image作るやつはあらゆるところにありそうだけど、どうもうまく動かないのよね。ここにメモ。

reference
https://github.com/sickp/docker-alpine-nginx/blob/master/versions/1.17.1-r1/Dockerfile

編集するのは以下
- NGINX_VERSION
- --with-http_stub_status_module らへんに追加したいモジュールを行追加

Dockerfile

gist https://gist.github.com/kujiy/75b13e140c960afc72281a7bbf8df4f8

FROM alpine:3.10.1
LABEL maintainer "Adrian B. Danieli - https://github.com/sickp"

EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]


ENV NGINX_VERSION 1.19.1

RUN set -ex \
  && apk add --no-cache \
  ca-certificates \
  libressl \
  pcre \
  zlib \
  && apk add --no-cache --virtual .build-deps \
  build-base \
  linux-headers \
  libressl-dev \
  pcre-dev \
  wget \
  zlib-dev \
  && cd /tmp \
  && wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \
  && tar xzf nginx-${NGINX_VERSION}.tar.gz \
  && cd /tmp/nginx-${NGINX_VERSION} \
  && ./configure \
  \
  --with-debug \
  \
  --prefix=/etc/nginx \
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --pid-path=/var/run/nginx.pid \
  --lock-path=/var/run/nginx.lock \
  \
  --user=nginx \
  --group=nginx \
  \
  --with-threads \
  \
  --with-file-aio \
  \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_realip_module \
  --with-http_addition_module \
  --with-http_sub_module \
  --with-http_dav_module \
  --with-http_flv_module \
  --with-http_mp4_module \
  --with-http_gunzip_module \
  --with-http_gzip_static_module \
  --with-http_auth_request_module \
  --with-http_random_index_module \
  --with-http_secure_link_module \
  --with-http_slice_module \
  --with-http_stub_status_module \
  \
  --http-log-path=/var/log/nginx/access.log \
  --http-client-body-temp-path=/var/cache/nginx/client_temp \
  --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
  --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
  --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
  --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
  \
  --with-mail \
  --with-mail_ssl_module \
  \
  --with-stream \
  --with-stream_ssl_module \
  --with-stream_realip_module \
  && make -j$(getconf _NPROCESSORS_ONLN) \
  && make install \
  && sed -i -e 's/#access_log  logs\/access.log  main;/access_log \/dev\/stdout;/' -e 's/#error_log  logs\/error.log  notice;/error_log stderr notice;/' /etc/nginx/nginx.conf \
  && adduser -D nginx \
  && mkdir -p /var/cache/nginx \
  && apk del .build-deps \
  && rm -rf /tmp/*

docker-compose.yml

version: '3'

services:
    reverseproxy:
        build:
          context: .
        container_name: test
        ports:
            - 82:80
        restart: always
        volumes:
            - ./nginx:/etc/nginx
        logging:
          options:
            max-size: "1m"
            max-file: "10"

./nginx には nginx official imageからコピってきた /etc/nginx が入ってます。

nginx posts

nginxのstatusを表示するモジュール /nginx_status
https://qiita.com/uturned0/items/b4eb6839d75050933c7f

nginxにモジュールを追加できるDockerfile
https://qiita.com/uturned0/items/3a0a7cb971edac40b11e

nginxリバプロで header を cookieに書き込む方法
https://qiita.com/uturned0/items/112b8faba403bd534d5c

nginxリバプロで、requestに入っているheaderをlogに出す方法
https://qiita.com/uturned0/items/31162eeb03af05c7dc4b

nginxだけでコンテンツを返す方法 - Load balancerのhealth checkに
https://qiita.com/uturned0/items/a8bcca111b75c5055ed9

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む