20200927のdockerに関する記事は22件です。

Install docker, docker-compose for debin10

目的

  • インストール
    • docker
    • docker-compose
  • docker data 保存先ディレクトリを移動する

Install docker

  • uninstall olds
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
  • setup repository
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    gnupg2 \
    software-properties-common

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
  • install docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

Install docker-compose

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

# インストール後にdocker-composeコマンドが失敗した場合は、パスをチェックします
# また、パス内の /usr/bin やその他のディレクトリへのシンボリックリンクを作成するなど
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

no sudo

  • sudo 無しで実行可能とする
sudo groupadd docker
sudo gpasswd -a $USER docker

docker data ディレクトリ移動

  • /etc/default/docker
# ファイル末尾に追加. -g の後に、docker data 保存先ディレクトリを指定
OPTIONS="-g /opt/docker"
  • /lib/systemd/system/docker.service
# option file 読み込み
EnvironmentFile=/etc/default/docker

# ExecStart 行の末尾に $OPTIONS を追記
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $OPTIONS
  • realod
sudo systemctl daemon-reload
sudo systemctl restart docker

参考サイト

https://docs.docker.com/engine/install/
https://mebee.info/2020/04/13/post-8593/
https://www.codeflow.site/ja/article/how-to-install-and-use-docker-on-debian-10
https://qiita.com/DQNEO/items/da5df074c48b012152ee

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

DockerのBASIC認証で作成した証明書と秘密鍵をAWS ALBで使用する方法

初めに

以下の手順に沿って進めます。
1. dockerがインストールされたAmazon LinuxにBASIC認証を作成する
2. BASIC認証で発行された秘密鍵と証明書を使用してALBを起動する

用語や認識など間違いがありましたら教えていただけると幸いです。

手順1 BASIC認証作成

まず初めにopenssl.cnfの253行目subjectAltNameをインスタンスのプライベートアドレスに書き換えます。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudoedit /etc/pki/tls/openssl.cnf

以下は書き換えた後、catで表示させたものです。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ cat -n /etc/pki/tls/openssl.cnf | head -n 255 | tail -n 5
   251
   252  # Include email address in subject alt name: another PKIX recommendation
   253  subjectAltName=IP:xxx.xxx.xxx.xxx
   254  # Copy issuer details
   255  # issuerAltName=issuer:copy

その後、以下のディレクトリを作ります。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ mkdir certs

上記ディレクトリに上記証明書(domain.crt)、秘密鍵(domain.key)を作成します。
Enter PEM pass phrase:パスフレーズの入力を求められます。
Verifying - Enter PEM pass phrase:2度目の入力が求められます。同じ値を入力します。
なお、このパスフレーズは以降使用しません。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ openssl req -newkey rsa:2048 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
Generating a 2048 bit RSA private key
........................................................................................+++
........+++
writing new private key to 'certs/domain.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

以下はすべて空白でエンターを押します。

Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

以下ではcertsディレクトリに移動しパスフレーズを削除します。
これをしないと次のエラーによりdockerの起動に失敗します。msg="tls: failed to parse private key"
Enter pass phrase for domain.key:では先ほどのパスフレーズを入力します。

[ec2-user@ip-xxx-xxx-xxx-xxx certs]$ openssl rsa -in domain.key -out new.key
Enter pass phrase for domain.key:
writing RSA key

証明書をコピーします。

[ec2-user@ip-xxx-xxx-xxx-xxx certs]$ sudo cp certs/domain.crt /etc/pki/ca-trust/source/anchors/xxx.xxx.xxx.xxx.crt

再起動を行います。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo update-ca-trust enable
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo update-ca-trust
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service docker restart

パスワードを作成します。
username、passwordにそれぞれユーザー名、パスワードを入力します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ docker run --entrypoint htpasswd registry:2.6.2 -Bbn username password > auth/htpasswd

プライベートレジストリ用のコンテナを起動します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ docker run -d -p 5000:5000 \
--restart=always \
--name registry \
-v `pwd`/auth:/auth \
-v `pwd`/certs:/certs \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
-e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \
-e "REGISTRY_HTTP_TLS_KEY=/certs/new.key" \
registry:2.6.2

ログインできることを確認します。

[ec2-user@ip-xxx-xxx-xxx-xxx certs]$ docker login https://xxx.xxx.xxx.xxx:5000
Username: testuser
Password:
WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

手順2 ALBを起動する

aws-cliを使用してログインします。
以下のアクセスキーXXXやシークレットアクセスキーYYYとなっている部分は、
IAM→ユーザーをクリック→認証情報をクリック で確認できます。

[ec2-user@ip-xxx-xxx-xxx-xxx certs]$ aws configure
AWS Access Key ID [None]: XXX
AWS Secret Access Key [None]: YYY
Default region name [None]: ap-northeast-1
Default output format [None]: json

certsディレクトリに移動しIAMに証明書をアップロードします。
my-secret-sertは証明書の名前になります。

[ec2-user@ip-xxx-xxx-xxx-xxx certs]$ aws iam upload-server-certificate --server-certificate-name my-server-cert \
--certificate-body file://domain.crt --private-key file://new.key 

ALBはVPC内にサブネットが2つ必要です。それらを作り終えたらEC2のコンソール画面に移動し、ロードバランサーをクリックします。
image.png

ALBを選択します。

image.png

HTTPSを選択します。
image.png

VPCの選択では先ほど作成したVPC、サブネットを選択します。
デフォルトの証明書の選択では、アップロードした証明書を選択します。

image.png

ルーティングの設定を以下のように行います。
image.png

ターゲットの登録では、選択したサブネット内のEC2をターゲットグループに登録できます。
以下のメッセージにより正常に作成されたかどうかを確認します。

image.png

参考記事

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

PyTorch+GPUをDockerで実装

はじめに

最近やっとDockerを使い始めました。
Dockerを使えば、いろんなPCでお手軽に深層学習できます。

環境(ホスト)

OS:Ubuntu 20.04
GPU:NVIDIA GeForce GTX 1080

GPUドライバをインストール

まず、ホストでGPUが使える環境にします。
$ nvidia-smi ですでにドライバがインストールされていれば、ここはスルーでいいです。
インストールの一例なので、参考までに

$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update
$ sudo apt install ubuntu-drivers-common
$ sudo apt dist-upgrade
$ sudo reboot (再起動)
$ sudo ubuntu-drivers autoinstall
$ sudo reboot (再起動)

$ nvidia-smiで Driverのバージョンやメモリの使用状況などが出ればOK!

Dockerをインストール

これは公式ホームページ (https://docs.docker.com/engine/install/ubuntu/) をそのまま実行

$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

$ sudo docker run hello-world で動作確認

Nvidia Container Toolkitをインストール

DockerでCUDAを使うために必要(だと思われます。)
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#
https://github.com/NVIDIA/nvidia-docker/issues/1186

$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

$ sudo apt-get update
$ sudo apt-get install -y nvidia-container-toolkit
$ sudo systemctl restart docker

Dockerfile

Dockerfileには仮想環境をどのようにするかを記述します。
1行目の FROM の部分でベースの環境を変更できます。(Ubuntu や CUDA のバージョンや cudnn の有無など)
nvidia/cuda の DockerHub を調べるといろいろ出てきます。(https://hub.docker.com/r/nvidia/cuda/tags)
また RUN の3行目で Python のライブラリを選択できます。

Dockerfile
FROM nvidia/cuda:11.0-devel-ubuntu20.04

RUN apt-get update
RUN apt-get install -y python3 python3-pip
RUN pip3 install torch torchvision

WORKDIR /work

COPY train.py /work/

ENV LIBRARY_PATH /usr/local/cuda/lib64/stubs

深層学習のスクリプト

先ほど作成した Dockerfile と同じディレクトリに train.py を実装します。
train.py は深層学習の Hello World! といえる MNIST というデータで学習します。
(引用:https://github.com/pytorch/examples/blob/master/mnist/main.py)

train.py
from __future__ import print_function
import argparse
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.optim.lr_scheduler import StepLR


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output


def train(args, model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % args.log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))
            if args.dry_run:
                break


def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)

    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))


def main():
    # Training settings
    parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
    parser.add_argument('--batch-size', type=int, default=64, metavar='N',
                        help='input batch size for training (default: 64)')
    parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',
                        help='input batch size for testing (default: 1000)')
    parser.add_argument('--epochs', type=int, default=14, metavar='N',
                        help='number of epochs to train (default: 14)')
    parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
                        help='learning rate (default: 1.0)')
    parser.add_argument('--gamma', type=float, default=0.7, metavar='M',
                        help='Learning rate step gamma (default: 0.7)')
    parser.add_argument('--no-cuda', action='store_true', default=False,
                        help='disables CUDA training')
    parser.add_argument('--dry-run', action='store_true', default=False,
                        help='quickly check a single pass')
    parser.add_argument('--seed', type=int, default=1, metavar='S',
                        help='random seed (default: 1)')
    parser.add_argument('--log-interval', type=int, default=10, metavar='N',
                        help='how many batches to wait before logging training status')
    parser.add_argument('--save-model', action='store_true', default=False,
                        help='For Saving the current Model')
    args = parser.parse_args()
    use_cuda = not args.no_cuda and torch.cuda.is_available()

    torch.manual_seed(args.seed)

    device = torch.device("cuda" if use_cuda else "cpu")

    kwargs = {'batch_size': args.batch_size}
    if use_cuda:
        kwargs.update({'num_workers': 1,
                       'pin_memory': True,
                       'shuffle': True},
                     )

    transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
        ])
    dataset1 = datasets.MNIST('../data', train=True, download=True,
                       transform=transform)
    dataset2 = datasets.MNIST('../data', train=False,
                       transform=transform)
    train_loader = torch.utils.data.DataLoader(dataset1,**kwargs)
    test_loader = torch.utils.data.DataLoader(dataset2, **kwargs)

    model = Net().to(device)
    optimizer = optim.Adadelta(model.parameters(), lr=args.lr)

    scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma)
    for epoch in range(1, args.epochs + 1):
        train(args, model, device, train_loader, optimizer, epoch)
        test(model, device, test_loader)
        scheduler.step()

    if args.save_model:
        torch.save(model.state_dict(), "mnist_cnn.pt")


if __name__ == '__main__':
    main()

とりあえず実行して、動作確認

Dockerfile をビルドして、仮想環境を作り、動かします。
train.py を実行中に $ nvidia-smi でGPUが使われてるか確認できます。

$ sudo docker build -t [コンテナ名] .
$ sudo docker run -it --gpus all [コンテナ名] /bin/bash
----以下コンテナ内で-----
$ python3 train.py

最後に

今回は PyTorch で仮想環境を作成しましたが、Dockerfile の中身を変更することで、
その他の深層学習ライブラリも使えると思います。
また、学習データが膨大な場合などは、docker のコマンドで学習データを仮想環境にマウントすることもできます。
それにしても、Dockerって便利ですね(笑)

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

Docker関連コマンド(自分用の備忘メモ)

Docker関連コマンド(自分用の備忘メモ)

1. Docker

Dockerのイメージ起動

docker run -it [IMAGE]

イメージに対する操作

確認
docker images
削除
docker rmi [IMAGE ID]

コンテナに対する操作

確認
docker ps -a
削除
docker rm [CONTAINER ID]

2. Docker-Compose

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

[Laravel] プロジェクト開始までの忘備録

概要

Laravel プロジェクトを開始するまでのコマンドをまとめた個人メモ。

前提条件

プロジェクトの開始

Version6系を使用し、tasklistというプロジェクト名で作成する

$ composer create-project --prefer-dist laravel/laravel tasklist ^6.0

DB作成

Dockerを使用し、mysql コンテナを立ち上げる。

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
4ded8e15debd        mysql               "docker-entrypoint.s…"   6 days ago          Up 6 days           0.0.0.0:3306->3306/tcp, 33060/tcp   mysql

プロセスで表示されたCONTAINER IDを使用し、コンテナに接続後DBの作成を行う
mysqlのパスワードはMYSQL_ROOT_PASSWORD引数で指定した値。

$ docker exec -it 4ded8e15debd86c73e637b0c612bf30f0cd9de0aec04b4c09a0f53a6fa16f35d bash
root@4ded8e15debd:/# mysql -u root -p -h 127.0.0.1
Enter password: mysql
mysql> DATABASE tasklist;
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| tasklist           |
+--------------------+
5 rows in set (0.03 sec)

DB 接続情報の定義

プロジェクト配下の .env ファイルで接続情報を定義する。
接続情報は個々の環境に合わせて変更すること。

$ cd tasklist 
$ vim .env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tasklist
DB_USERNAME=root
DB_PASSWORD=mysql

DB接続の確認

Webアプリが正常にDB接続できているか確認を行う。
以下のように表示されている場合接続できている。

$ php artisan tinker
Psy Shell v0.10.4 (PHP 7.4.10 — cli) by Justin Hileman
>>> DB::reconnect();
=> Illuminate\Database\MySqlConnection {#3233}

タイムゾーンの変更

デフォルトではUTCのため、Asia/Tokyoに変更する。

$ vim config/app.php

'timezone' => 'Asia/Tokyo',

アプリの起動

内部サーバを起動させる。
デフォルトで用意されている welcome.blade.php のviewが表示される

$ php artisan serve --host=127.0.0.1 --port=8080 

備考

コンテナを停止する際は以下コマンドを実行すること。

$ docker stop { CONTAINER ID }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Laravel] プロジェクト開始までのコマンド忘備録

概要

Laravel プロジェクトを開始するまでのコマンドをまとめた個人メモ。

前提条件

プロジェクトの開始

Version6系を使用し、tasklistというプロジェクト名で作成する

$ composer create-project --prefer-dist laravel/laravel tasklist ^6.0

DB作成

Dockerを使用し、mysql コンテナを立ち上げる。

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
4ded8e15debd        mysql               "docker-entrypoint.s…"   6 days ago          Up 6 days           0.0.0.0:3306->3306/tcp, 33060/tcp   mysql

プロセスで表示されたCONTAINER IDを使用し、コンテナに接続後DBの作成を行う
mysqlのパスワードはMYSQL_ROOT_PASSWORD引数で指定した値。

$ docker exec -it 4ded8e15debd86c73e637b0c612bf30f0cd9de0aec04b4c09a0f53a6fa16f35d bash
root@4ded8e15debd:/# mysql -u root -p -h 127.0.0.1
Enter password: mysql
mysql> CREATE DATABASE tasklist;
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| tasklist           |
+--------------------+
5 rows in set (0.03 sec)

DB 接続情報の定義

プロジェクト配下の .env ファイルで接続情報を定義する。
接続情報は個々の環境に合わせて変更すること。

$ cd tasklist 
$ vim .env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tasklist
DB_USERNAME=root
DB_PASSWORD=mysql

DB接続の確認

Webアプリが正常にDB接続できているか確認を行う。
以下のように表示されている場合接続できている。

$ php artisan tinker
Psy Shell v0.10.4 (PHP 7.4.10 — cli) by Justin Hileman
>>> DB::reconnect();
=> Illuminate\Database\MySqlConnection {#3233}

タイムゾーンの変更

デフォルトではUTCのため、Asia/Tokyoに変更する。

$ vim config/app.php

'timezone' => 'Asia/Tokyo',

アプリの起動

内部サーバを起動させる。
デフォルトで用意されている welcome.blade.php のviewが表示される

$ php artisan serve --host=127.0.0.1 --port=8080 

備考

コンテナを停止する際は以下コマンドを実行すること。

$ docker stop { CONTAINER ID }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.dockerignoreが効かない?.gitignoreとは書き方が違うよ!

この記事は

.dockerignoreと.gitignore、名前が似ているし書き方も似ているので同じように書けばよいと思っていましたが、違いました。この記事では違いを見ていきます。

対象読者

.gitignoreは書いたことがあるけれど、.dockerignoreはあまり書いたことがない人

ポイント

.gitignoreの仕様は 公式ページのgitignoreのページ に記載されています。
日本語だとQiitaの .gitignoreの仕様詳解 が分かりやすいです。

.dockerignoreの仕様は 公式ページのdocker build#dockerignore に記載されています。

主なルールは3つです。

  • パターンマッチングには Go 言語の filepath.Match ルールが用いられています。 
  • 特別なワイルドカード文字列 ** をサポートしています。 これは複数のディレクトリ(ゼロ個を含む)にマッチします。
  • 行頭を感嘆符 ! で書き始めると、それは除外に対しての例外を指定するものとなります。

.dockerignoreとは

.dockerignoreと.gitignoreの違いを説明する前に、docker build時のファイル転送と.dockerignoreの役割を説明します。

docker build時のファイル転送

Dockerfileをビルドする際、dockerはビルドコンテキスト以下をtarでまとめています。これは対象のディレクトリをdockerデーモンに転送するためです。
このtarの中には、COPYやADDされないファイルも含まれます。ビルドコンテキスト以下の全てのファイルが含まれるのです。

build_context.png

.dockerignore

dockerビルドに必要ない(tarの中に入れたくない)ファイルは.dockerignoreに記載します。
.dockerignoreを作成することで、ビルド時間の短縮、docker imageサイズの最適化、機密情報(パスワードなど)の不本意な漏洩の防止、等の効果があります。

ビルドコンテキストルート

ビルドコンテキストルートは、docker buildで使用するパスです。(Dockerfileの場所ではありません)

docker build -f path/to/Dockerfile src
                                   ---
                              ↑ docker buildの引数に指定しているパスがビルドコンテキストルート ↑

上の例だと、srcがビルドコンテキストルートです。上記の例の場合、.dockerignoreはsrcディレクトリに配置します。

.dockerignoreと.gitignoreの違い

さて本題です。.dockerignoreと.gitignore、目的も書き方も似ていますが、実装は同じではありません。仕様も違っています。

パスの指定の仕方

.gitignore

.gitignoreでは書かれたファイルorディレクトリ名は.gitignoreファイル以下の階層であれば、どの階層であっても無視されます。

例えば、

.gitignore
target

と記載すると、

target
src/target
path/a/b/target

などが無視されます。

.dockerignore

.dockerignoreでは、パスはすべて.dockerignoreが置かれているパスからの相対パスで記載します。1

例えば、

.dockerignore
target

と記載すると、

target

のみが無視され、

src/target
path/a/b/target

は無視されません。

.gitignoreのように任意の階層を対象にしたい場合は

dockerignore
**/target

と記載します。

サブディレクトリにあるignorefile

.gitignore

.gitignoreの場合、.gitignoreをサブディレクトリにも配置することができます。その場合は対象ファイルに近い方のルールが優先されます。

gitignore_directory.png

.dockerignore

.dockerignoreはビルドコンテキストルートにある.dockerignoreしか読み込まれません。サブディレクトリにある.dcokerignoreファイルは読み込まれません。

dockerignore_directory_2.png

Dockerfileのディレクトリとビルドコンテキストが異なる場合に注意が必要です。Dockerfileと同じ場所に.gitignoreを置くのではなく、ビルドコンテキストに.dockerignoreを配置します。

あとがき

もしかしてもう少し違いがあるかもしれませんが、今のところ見つけた違いはこのくらいでした。
快適なdockerライフを。

環境

  • Docker: 19.03.12
  • Docker for Mac: 2.3.0.5

参考資料リンク


  1. .gitignoreと同様にパスの先頭に / を付けることも可能です。 

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

docker run --help 日本語訳

docker run --help 実行時に表示されるドキュメントの日本語訳。

使用法:

docker run [OPTIONS] IMAGE [COMMAND] [ARG ...]

新しいコンテナでコマンドを実行する

オプション:

  • --add-host list カスタムのホストから IP へのマッピングを追加します( host:ip )
  • -a, -attach list STDIN, STDOUT, または STDERR に接続
  • --blkio-weight uint16 ブロック IO(相対重み)、10 から 1000、または無効にする場合は 0(デフォルトは 0)
  • --blkio-weight-device list ブロック IO の重み(デバイスの相対的な重み)(デフォルトは [] )
  • --cap-add list Linux 機能を追加する
  • --cap-drop list Linux 機能の削除
  • --cgroup-parent string コンテナーのオプションの親 cgroup
  • --cidfile string コンテナ ID をファイルに書き込みます
  • --cpu-period int CPU CFS(Completely Fair Scheduler)期間の制限
  • --cpu-quota int CPU CFS(Completely Fair Scheduler)の割り当てを制限する
  • --cpu-rt-period int CPU のリアルタイム期間をマイクロ秒で制限する
  • --cpu-rt-runtime int CPU リアルタイムランタイムをマイクロ秒単位で制限する
  • -c, -cpu-shares int CPU シェア(相対ウェイト)
  • --cpus decimal CPU の数
  • --cpuset-cpus string 実行を許可するCPU(0-3, 0, 1)
  • --cpuset-mems string 実行を許可する MEM(0-3, 0, 1)
  • -d, -detach コンテナーをバックグラウンドで実行し、コンテナー ID を表示する
  • --detach-keys string コンテナーを切り離すためのキーシーケンスをオーバーライドする
  • --device list コンテナにホストデバイスを追加する
  • --device-cgroup-rule list ルールを cgroup 許可デバイスリストに追加します
  • --device-read-bps list デバイスからの読み取り速度(1 秒あたりのバイト数)を制限します(デフォルトは [] )
  • --device-read-iops list デバイスからの読み取り速度(1 秒あたりの IO)を制限する(デフォルトは [] )
  • --device-write-bps list デバイスへの書き込み速度(1 秒あたりのバイト数)を制限します(デフォルトは [] )
  • --device-write-iops list デバイスへの書き込み速度(1 秒あたりの IO)を制限します(デフォルトは [] )
  • --disable-content-trust 画像検証をスキップ(デフォルトは true)
  • --dns list カスタム DNS サーバーを設定する
  • --dns-option list DNS オプションを設定する
  • --dns-search list カスタム DNS 検索ドメインを設定する
  • --domainname string コンテナ NIS メイン名
  • --entrypoint string イメージのデフォルト ENTRYPOINT を上書きする
  • -e, -env list 環境変数を設定する
  • --env-file list 環境変数のファイルを読み込む
  • --expose list ポートまたはポートの範囲を公開する
  • --gpus gpu-request コンテナーに追加する GPU デバイス(すべての GPU を渡すには all )
  • --group-add list 参加するグループをさらに追加
  • --health-cmd string コンテナの健常性をチェックするために実行するコマンド
  • --health-interval duration チェックの実行間隔( ms | s | m | h )(デフォルトは 0s )
  • --health-retries int 異常を報告するために必要な連続失敗数を指定する
  • --health-start-period duration health-retries のカウントダウン( ms | s | m | h )を開始する前にコンテナを初期化する開始期間(デフォルトは 0s )
  • --health-timeout duration 1 つのチェックの実行を許可する最大時間( ms | s | m | h )(デフォルトは 0s )
  • --help 使用法を表示する。
  • -h, --hostname string コンテナのホスト名
  • --init シグナルを転送し、プロセスを取得するコンテナ内で初期化を実行します
  • -i, -interactive 接続されていなくても STDIN を開いたままにします
  • --ip string IPv4 アドレス(172.30.100.104 など)
  • --ip6 string IPv6 アドレス(例: 2001:db8::33)
  • --ipc string 使用する IPC モード
  • --isolation string コンテナ隔離技術
  • --kernel-memory bytes カーネルメモリ制限
  • -l, --label list コンテナにメタデータを設定する
  • --label-file list ファイルからラベルの一覧を読み取る。 ラベルの一覧は行区切りで記述する。
  • --link list 別のコンテナへのリンクを追加
  • --link-local-ip list コンテナ IPv4 / IPv6 リンクローカルアドレス
  • --log-driver string コンテナーのロギングドライバー
  • --log-opt list ログドライバーオプション
  • --mac-address string コンテナの MAC アドレス(例: 92:d0:c6:0a:29:33)
  • -m, --memory bytes メモリ制限
  • --memory-reservation bytes メモリのソフト制限
  • --memory-swap bytes スワップ制限はメモリ + スワップに等しい: -1 は無制限のスワップを有効にします
  • --memory-swappiness int コンテナメモリの swappiness を調整する(0 から 100)(デフォルトは -1)
  • --mount mount コンテナーにファイルシステムのマウントを追加します
  • --name string コンテナーに名前を割り当てる
  • --network network コンテナーをネットワークに接続する
  • --network-alias list コンテナーのネットワークスコープのエイリアスを追加する
  • --no-healthcheck コンテナ指定のヘルスチェックを無効にする
  • --oom-kill-disable OOM キラーを無効にする
  • --oom-score-adj int ホストの OOM 設定を調整する(-1000 から 1000)
  • --pid string 使用する PID 名前空間
  • --pids-limit int コンテナー PID の制限を調整する(無制限の場合は -1 に設定)
  • --platform string サーバーがマルチプラットフォーム対応の場合はプラットフォームを設定する
  • --privileged コンテナに拡張特権を与える
  • -p, --publish list コンテナのポートをホストに公開する
  • -P, --publish-all 公開されているすべてのポートをランダムなポートに公開する
  • --read-only コンテナーのルートファイルシステムを読み取り専用としてマウントする
  • --restart string コンテナの終了時に適用する再起動ポリシー(デフォルトは no )
  • --rm 終了時にコンテナを自動的に削除します
  • --runtime string コンテナに使用するランタイム
  • --security-opt list セキュリティオプション
  • --shm-size bytes /dev/shm のサイズ
  • --sig-proxy プロセスへのプロキシ受信シグナル(デフォルトは true)
  • --stop-signal string コンテナーを停止する信号(デフォルトは 15 )
  • --stop-timeout int コンテナーを停止するタイムアウト期間(秒単位)
  • --storage-opt list コンテナーのストレージドライバーオプション
  • --sysctlマップ Sysctl オプション(デフォルトのマップ [])
  • --tmpfs list tmpfs ディレクトリをマウントする
  • -t, --tty 疑似 TTY を割り当てる
  • --ulimit ulimit Ulimit オプション(デフォルト [])
  • -u, -user string ユーザー名または UID(形式: : <name|uid>[:<group|gid>] )
  • --userns string 使用するユーザー名前空間
  • --uts string 使用する UTS 名前空間
  • -v, --volume list ボリュームをバインドマウントする
  • --volume-driver string コンテナーのオプションのボリュームドライバー
  • --volumes-from list 指定されたコンテナからボリュームをマウントします
  • -w, --workdir string コンテナ内の作業ディレクトリ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Clean My Mac Xを使った後にDockerが使えなくなった事件

この記事について

MacOSをアップデートしようと思ったのですが、ストレージが「その他」でいっぱいになり、いらないファイルやらを消してくれる「Clean My Mac X」を使用して、Macの再起動後にDocekrを立ち上げようとすると、添付画像のエラーが表示されました。

今回はこのエラーを解決するためにやったことをまとめた記事です。

スクリーンショット 2020-09-27 7.49.55.png

Clean My Mac Xとは

CleanMyMac Xは、システム内のキャッシュファイルやジャンク(破損)ファイル、使用していないファイル(言語データや過去の古いファイル)などを、スキャンして削除できるアプリです。

https://www.cleanmymac.jp/
https://o9sec.com/2019/08/14/2978/

環境

Mac Catalina:10.15.5
Docker:2.3.0.3?
※DockerのバージョンはDockerを開く事ができなくて確認できませんが、今年の6月ごろに使い始めたので恐らくこのバージョンです。

問題解決に参考した記事

https://github.com/docker/for-mac/issues/4526
参考記事だと、古いバージョンをインストールすると問題が解決された方もいっらしゃるようですが、私の場合は解決できませんでした。

やったこと

  • Dockerをアンインストールしてから再度インストール

  • Docker Desktop Community 2.2.0.5でインストール

◆参考記事内でできなかったこと
https://github.com/docker/for-mac/issues/4526#issuecomment-640237696
いくつかgoodが押されているのでやってみたみたいのですが、日本語に訳しても何をすればいいかわからないので挑戦できていないです。

真似できなかった参考記事の日本語訳

BIOSで「Intel(VMX)仮想化テクノロジー」を有効にする必要があります。
これを有効にする場所を知るには、BIOSメーカーを確認してください。
これは「仮想化(VT-x)」とは異なります
それらを有効にすると、再び機能します。

私の場合の解決方法

Clean My Mac Xのおかげでストレージにアップデートするための枠ができたので、MacOSをアップデートすると、ちゃんと使えるようになっていました!

反省

バージョンいくつか試してうまくいかないようならそもそもシステム周りのファイルを消された可能性があったから、無闇に削除するとえらい目に合っちゃう。。。

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

Redmineのコードリーディング環境をDockerで構築する

概要

redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。

  • redmineのmasterブランチのコードがDocker上で動作する
  • Debug用のツールが使える

モチベーション

動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。

なぜコードリーディングしたいのか?

人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。

なぜRedmineか?

Redmineを選んだのは以下の理由です。

  • 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
  • 長年メンテナンスされており、世界中で使用されている。
  • 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。

環境構築

以下を参考にすすめていきます。

リポジトリの用意

  1. redmineのレポジトリをフォーク
  2. フォークしたリポジトリをクローン
  3. redmineディレクトリに移動
  4. masterブランチから別ブランチを切る(自分はcode_readingにしました)

Docker関連ファイルの作成

redmineディレクトリ直下に以下のファイルを作成します。

  • Dockerfile
  • docker-compose.yml
  • entrypoint.sh

ファイルの内容は以下の通りにします。

Dockerfile

RedmineのGemfileがconfig/database.ymlを参照しているため、COPY . /redmineをした後にbundle installをする必要があります。
ちなみに参照して何をしているかというと、使用するDBにあわせてインストールするGemを変えています。例えばconfig/database.ymlにpostgresの接続情報が書いてあると、postgresに接続するためのGemがインストールされます。

Dockerfile
FROM ruby:2.5

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn
RUN mkdir /redmine
WORKDIR /redmine
COPY Gemfile /redmine/Gemfile
COPY Gemfile.lock /redmine/Gemfile.lock
COPY . /redmine
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /redmine/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

docker-compose.yml

コメントアウトしているのはruby-debug/ruby-debug-ide用の設定です。
導入しましたが自分の環境では動作が安定しなかったので一旦使わないようにしています。

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    ports:
        - "5433:5432"
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    # command: bash -c "rm -f tmp/pids/server.pid && bundle exec rdebug-ide --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0"
    command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b 0.0.0.0"
    volumes:
      - .:/redmine
    ports:
      - "3003:3000"
      # - "1234:1234"
      # - "26162:26162"
    stdin_open: true
    tty: true
    depends_on:
      - db

デバッグ用のGemの追記

などの記事を参考にGemfile.に以下を追加します。

  • better_errors
  • binding_of_caller
  • pry-rails
  • pry-byebug
Gemfile
group :development do
  gem "yard" #この下に追記する
  gem "better_errors"
  gem "binding_of_caller"
  gem "pry-rails"
  gem "pry-byebug"
  # 安定動作しなかったのでコメントアウト
  # gem "ruby-debug-ide"
  # gem "debase"      
end

database.ymlの設定

config/database.ymlを作成し以下の内容にします。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password: password

development:
  <<: *default
  database: redmine_development

test:
  <<: *default
  database: redmine_test

production:
  <<: *default
  database: redmine

また、better_errosをDocker上の環境で使えるようにするため、development.rbに以下を追記します。

config/enviroments/development.rb
BetterErrors::Middleware.allow_ip! "0.0.0.0/0"

環境の立ち上げ

ファイルの用意が完了したのでコンテナを起動し、アプリケーションを動かします。

# コンテナイメージのビルド
$ docker-compose build
# コンテナの起動
$ docker-compose up -d
# DBの作成
$ docker-compose run --rm web rake db:create
# マイグレーションの実行
$ docker-compose run --rm web bin/bundle exec rake db:migrate
# Redmineのデフォルトデータ投入タスク
$ docker-compose run --rm web bin/bundle exec rake redmine:load_default_data

起動が成功していればdocker-compse psで以下のようにStatusがUpになります。

$ dcom ps
    Name                   Command               State    Ports                                  
--------------------------------------------------------------------------------
redmine_db_1    docker-entrypoint.sh postgres    Up      0.0.0.0:5433->5432/tcp                                                  
redmine_web_1   entrypoint.sh bash -c rm - ...   Up      0.0.0.0:3003->3000/tcp

この後にhttp://localhost:3003にアクセスするとRedmineの画面が表示されます。
また、最初はIDとパスワード共にadminでログインすることができます。
これで環境構築は完了です。

pry-byebugによるデバッグ

docker-compose upでコンテナが起動している状態でコンテナにアタッチします。

$ docker attach redmine_web_1

確認したいコードの該当箇所にbinding.pryを追記します。以下の例はRedmineのルートパスにアクセスした時に実行されるwellcome#indexに追加しています。

app/controllers/welcome_controller.rb
  def index
    binding.pry #調べたいところに追加する
    @news = News.latest User.current
  end

この状態でhttp://localhost:3003にアクセスするとターミナルに以下の内容が表示されステップ実行などができるようになります。

From: /redmine/app/controllers/welcome_controller.rb:25 WelcomeController#index:

    23: def index
    24:   binding.pry
 => 25:   @news = News.latest User.current
    26: end

[1] pry(#<WelcomeController>)> Started GET "/" for 172.18.0.1 at 2020-09-27 07:41:34 +0000
[1] pry(#<WelcomeController>)> 

[1] pry(#<WelcomeController>)>の箇所にコマンドを打つことでステップ実行などができます。

  • next
    • ステップイン
  • step
    • ステップオーバー
  • continue
    • プログラムの実行を続行しpryを終了

以上

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

Redmineのコードリーディング環境をDocker上に構築する

概要

redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。

  • redmineのmasterブランチのコードがDocker上で動作する
  • Debug用のツールが使える

モチベーション

動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。

なぜコードリーディングしたいのか?

人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。

なぜRedmineか?

Redmineを選んだのは以下の理由です。

  • 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
  • 長年メンテナンスされており、世界中で使用されている。
  • 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。

環境構築

以下を参考にすすめていきます。

リポジトリの用意

  1. redmineのレポジトリをフォーク
  2. フォークしたリポジトリをクローン
  3. redmineディレクトリに移動
  4. masterブランチから別ブランチを切る(自分はcode_readingにしました)

Docker関連ファイルの作成

redmineディレクトリ直下に以下のファイルを作成します。

  • Dockerfile
  • docker-compose.yml
  • entrypoint.sh

ファイルの内容は以下の通りにします。

Dockerfile

RedmineのGemfileがconfig/database.ymlを参照しているため、COPY . /redmineをした後にbundle installをする必要があります。
ちなみに参照して何をしているかというと、使用するDBにあわせてインストールするGemを変えています。例えばconfig/database.ymlにpostgresの接続情報が書いてあると、postgresに接続するためのGemがインストールされます。
Gemfileで指定するgemを動的に変えるという発想があまりなかったので既に学びがあったと感じています。

Dockerfile
FROM ruby:2.5

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn
RUN mkdir /redmine
WORKDIR /redmine
COPY Gemfile /redmine/Gemfile
COPY Gemfile.lock /redmine/Gemfile.lock
COPY . /redmine
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /redmine/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

docker-compose.yml

コメントアウトしているのはruby-debug/ruby-debug-ide用の設定です。
導入しましたが自分の環境では動作が安定しなかったので一旦使わないようにしています。

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    ports:
        - "5433:5432"
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    # command: bash -c "rm -f tmp/pids/server.pid && bundle exec rdebug-ide --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0"
    command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b 0.0.0.0"
    volumes:
      - .:/redmine
    ports:
      - "3003:3000"
      # - "1234:1234"
      # - "26162:26162"
    stdin_open: true
    tty: true
    depends_on:
      - db

デバッグ用のGemの追記

などの記事を参考にGemfile.に以下を追加します。

  • better_errors
  • binding_of_caller
  • pry-rails
  • pry-byebug
Gemfile
group :development do
  gem "yard" #この下に追記する
  gem "better_errors"
  gem "binding_of_caller"
  gem "pry-rails"
  gem "pry-byebug"
  # 安定動作しなかったのでコメントアウト
  # gem "ruby-debug-ide"
  # gem "debase"      
end

database.ymlの設定

config/database.ymlを作成し以下の内容にします。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password: password

development:
  <<: *default
  database: redmine_development

test:
  <<: *default
  database: redmine_test

production:
  <<: *default
  database: redmine

また、better_errosをDocker上の環境で使えるようにするため、development.rbに以下を追記します。

config/enviroments/development.rb
BetterErrors::Middleware.allow_ip! "0.0.0.0/0"

環境の立ち上げ

ファイルの用意が完了したのでコンテナを起動し、アプリケーションを動かします。

# コンテナイメージのビルド
$ docker-compose build
# コンテナの起動
$ docker-compose up -d
# DBの作成
$ docker-compose run --rm web rake db:create
# マイグレーションの実行
$ docker-compose run --rm web bin/bundle exec rake db:migrate
# Redmineのデフォルトデータ投入タスク
$ docker-compose run --rm web bin/bundle exec rake redmine:load_default_data

起動が成功していればdocker-compse psで以下のようにStatusがUpになります。

$ dcom ps
    Name                   Command               State    Ports                                  
--------------------------------------------------------------------------------
redmine_db_1    docker-entrypoint.sh postgres    Up      0.0.0.0:5433->5432/tcp                                                  
redmine_web_1   entrypoint.sh bash -c rm - ...   Up      0.0.0.0:3003->3000/tcp

この後にhttp://localhost:3003にアクセスするとRedmineの画面が表示されます。
また、最初はIDとパスワード共にadminでログインすることができます。
これで環境構築は完了です。

pry-byebugによるデバッグ

docker-compose upでコンテナが起動している状態でコンテナにアタッチします。

$ docker attach redmine_web_1

確認したいコードの該当箇所にbinding.pryを追記します。以下の例はRedmineのルートパスにアクセスした時に実行されるwellcome#indexに追加しています。

app/controllers/welcome_controller.rb
  def index
    binding.pry #調べたいところに追加する
    @news = News.latest User.current
  end

この状態でhttp://localhost:3003にアクセスするとターミナルに以下の内容が表示されステップ実行などができるようになります。

From: /redmine/app/controllers/welcome_controller.rb:25 WelcomeController#index:

    23: def index
    24:   binding.pry
 => 25:   @news = News.latest User.current
    26: end

[1] pry(#<WelcomeController>)> Started GET "/" for 172.18.0.1 at 2020-09-27 07:41:34 +0000
[1] pry(#<WelcomeController>)> 

[1] pry(#<WelcomeController>)>の箇所にコマンドを打つことでステップ実行などができます。

  • next
    • ステップイン
  • step
    • ステップオーバー
  • continue
    • プログラムの実行を続行しpryを終了

以上

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

Redmineのコードリーディング用環境をDocker上に構築する

概要

redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。

  • redmineのmasterブランチのコードがDocker上で動作する
  • Debug用のツールが使える

モチベーション

動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。

なぜコードリーディングしたいのか?

人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。

なぜRedmineか?

Redmineを選んだのは以下の理由です。

  • 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
  • 長年メンテナンスされており、世界中で使用されている。
  • 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。

環境構築

以下を参考にすすめていきます。

リポジトリの用意

  1. redmineのレポジトリをフォーク
  2. フォークしたリポジトリをクローン
  3. redmineディレクトリに移動
  4. masterブランチから別ブランチを切る(自分はcode_readingにしました)

Docker関連ファイルの作成

redmineディレクトリ直下に以下のファイルを作成します。

  • Dockerfile
  • docker-compose.yml
  • entrypoint.sh

ファイルの内容は以下の通りにします。

Dockerfile

RedmineのGemfileがconfig/database.ymlを参照しているため、COPY . /redmineをした後にbundle installをする必要があります。
ちなみに参照して何をしているかというと、使用するDBにあわせてインストールするGemを変えています。例えばconfig/database.ymlにpostgresの接続情報が書いてあると、postgresに接続するためのGemがインストールされます。
Gemfileで指定するgemを動的に変えるという発想があまりなかったので既に学びがあったと感じています。

Dockerfile
FROM ruby:2.5

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn
RUN mkdir /redmine
WORKDIR /redmine
COPY Gemfile /redmine/Gemfile
COPY Gemfile.lock /redmine/Gemfile.lock
COPY . /redmine
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /redmine/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

docker-compose.yml

コメントアウトしているのはruby-debug/ruby-debug-ide用の設定です。
導入しましたが自分の環境では動作が安定しなかったので一旦使わないようにしています。

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    ports:
        - "5433:5432"
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    # command: bash -c "rm -f tmp/pids/server.pid && bundle exec rdebug-ide --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0"
    command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b 0.0.0.0"
    volumes:
      - .:/redmine
    ports:
      - "3003:3000"
      # - "1234:1234"
      # - "26162:26162"
    stdin_open: true
    tty: true
    depends_on:
      - db

デバッグ用のGemの追記

などの記事を参考にGemfile.に以下を追加します。

  • better_errors
  • binding_of_caller
  • pry-rails
  • pry-byebug
Gemfile
group :development do
  gem "yard" #この下に追記する
  gem "better_errors"
  gem "binding_of_caller"
  gem "pry-rails"
  gem "pry-byebug"
  # 安定動作しなかったのでコメントアウト
  # gem "ruby-debug-ide"
  # gem "debase"      
end

また、better_errosをDocker上の環境で使えるようにするため、development.rbに以下を追記します。

config/enviroments/development.rb
BetterErrors::Middleware.allow_ip! "0.0.0.0/0"

database.ymlの設定

config/database.ymlを作成し以下の内容にします。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password: password

development:
  <<: *default
  database: redmine_development

test:
  <<: *default
  database: redmine_test

production:
  <<: *default
  database: redmine

環境の立ち上げ

ファイルの用意が完了したのでコンテナを起動し、アプリケーションを動かします。

# 空のGemfile.lockを作る
$ touch Gemfile.lock
# コンテナイメージのビルド
$ docker-compose build
# コンテナの起動
$ docker-compose up -d
# DBの作成
$ docker-compose run --rm web rake db:create
# マイグレーションの実行
$ docker-compose run --rm web bin/bundle exec rake db:migrate
# Redmineのデフォルトデータ投入タスク
$ docker-compose run --rm web bin/bundle exec rake redmine:load_default_data

起動が成功していればdocker-compse psで以下のようにStatusがUpになります。

$ dcom ps
    Name                   Command               State    Ports                                  
--------------------------------------------------------------------------------
redmine_db_1    docker-entrypoint.sh postgres    Up      0.0.0.0:5433->5432/tcp                                                  
redmine_web_1   entrypoint.sh bash -c rm - ...   Up      0.0.0.0:3003->3000/tcp

この後にhttp://localhost:3003にアクセスするとRedmineの画面が表示されます。
また、最初はIDとパスワード共にadminでログインすることができます。
これで環境構築は完了です。

pry-byebugによるデバッグ

docker-compose upでコンテナが起動している状態でコンテナにアタッチします。

$ docker attach redmine_web_1

確認したいコードの該当箇所にbinding.pryを追記します。以下の例はRedmineのルートパスにアクセスした時に実行されるwellcome#indexに追加しています。

app/controllers/welcome_controller.rb
  def index
    binding.pry #調べたいところに追加する
    @news = News.latest User.current
  end

この状態でhttp://localhost:3003にアクセスするとターミナルに以下の内容が表示されステップ実行などができるようになります。

From: /redmine/app/controllers/welcome_controller.rb:25 WelcomeController#index:

    23: def index
    24:   binding.pry
 => 25:   @news = News.latest User.current
    26: end

[1] pry(#<WelcomeController>)> Started GET "/" for 172.18.0.1 at 2020-09-27 07:41:34 +0000
[1] pry(#<WelcomeController>)> 

[1] pry(#<WelcomeController>)>の箇所にコマンドを打つことでステップ実行などができます。

  • next
    • ステップイン
  • step
    • ステップオーバー
  • continue
    • プログラムの実行を続行しpryを終了

以上

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

Golang + Gin + Dockerのホットリロード、VSCodeデバッグ環境の構築

概要

Go言語のフレームワークGinの開発環境の構築。(ホットリロード、VSCodeデバッグ対応)

今回のコードはGitHubに公開してあります。
https://github.com/yolo-lin/go-demo

環境

  • MacOS 10.15.6
  • go version go1.15.2 darwin/amd64

導入するパッケージ

Gin:Goのフレームワーク
cosmtrek/air:ホットリロード
delve:デバッグ

事前準備

  • Goのインストール:公式からインストール
  • Go Modulesで依存関係を管理するため、環境変数GO111MODULEをonにする
.zshrc
export GO111MODULE=on
  • Go Modulesの初期化
/src
$ go mod init パッケージ名

ディレクトリ構成

Ginのディレクトリ構成は特に決まってないので、以下は自己流です。
メインのソースコードは全部srcの下に配置する。今後はmodelscontrollersもsrcに追加する予定です。

.
├── .vscode
│   └── launch.json
├── docker
│   ├── go
│   │   └── Dockerfile
│   └── mysql
│       └── Dockerfile
├── src
│   ├── go.mod
│   ├── go.sum
│   ├── .air.toml
│   └── main.go
│
└── docker-compose.yml

Docker

Go

/docker/go/Dockerfile
FROM golang:1.15.2

ENV GO111MODULE=on

COPY src/ /go/src/app/

WORKDIR /go/src/app

# cosmtrek/airのインストール
RUN go get -u github.com/cosmtrek/air
# delveのインストール
RUN go get -u github.com/go-delve/delve/cmd/dlv

# airの起動
CMD air -c .air.toml

MySQL

/docker/go/Dockerfile
FROM mysql:8.0

RUN chown -R mysql /var/lib/mysql && \
    chgrp -R mysql /var/lib/mysql

docker-compose

./docker-compose.yml
version: '3'

networks:
    backend:
      driver: bridge

services:
    go:
        container_name: go
        build:
            context: .
            dockerfile: ./docker/go/Dockerfile
        ports:
            - 8080:8080
            - 2345:2345
        links:
            - mysql
        tty: true
        volumes:
            - ./src:/go/src/app
        depends_on:
            - mysql
        security_opt:
            - seccomp:unconfined
        cap_add:
            - SYS_PTRACE
        networks:
            - backend

    mysql:
        container_name: mysql
        build:
            context: .
            dockerfile: ./docker/mysql/Dockerfile
        environment:
            MYSQL_USER: root
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: demo
        hostname: mysql
        ports:
            - "3306:3306"
        volumes:
            - ./docker/mysql/data:/var/lib/mysql
        security_opt:
            - seccomp:unconfined
        networks:
            - backend

    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        environment:
            - PMA_ARBITRARY=1
            - PMA_HOST=mysql
            - PMA_USER=root
            - PMA_PASSWORD=password
        ports:
            - "8081:80"
        depends_on:
            - mysql
        networks:
            - backend

cosmtrek/airの設定

公式のair_example.tomlを流用

以下デバッグ用の記述を追記

/src/.air.toml
# Debug
#full_bin = "APP_ENV=dev APP_USER=air /go/bin/dlv exec ./tmp/main --headless=true --listen=:2345 --api-version=2 --accept-multiclient"
/src/.air.toml
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format

# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"

[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -o ./tmp/main ."
# Binary file yields from `cmd`.
bin = "tmp/main"

# Customize binary.
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"

# Debug
#full_bin = "APP_ENV=dev APP_USER=air /go/bin/dlv exec ./tmp/main --headless=true --listen=:2345 --api-version=2 --accept-multiclient"

# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms

[log]
# Show log time
time = false

[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# Delete tmp directory on exit
clean_on_exit = true

これで、docker-compose up -dしたら、自動的に設定ファイルを適応し、ホットリロード化される。

デバッグ

vscode

Goの拡張機能をインストール、以下デバッグ設定ファイルを追加する。

/.vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Remote",
            "type": "go",
            "request": "launch",
            "mode": "remote",
            "program": "${workspaceFolder}",
            "port": 2345,
            "host": "127.0.0.1",
            "showLog": true,
        }
    ]
}

デバッグが必要な場合、cosmtrek/airの設定を変更する。
開発用とデバッグ用のfull_binを交換し、docker-compose再起動したら、vscodeでデバッグ可能になります。

/src/.air.toml
# Customize binary.
# full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"

# Debug
full_bin = "APP_ENV=dev APP_USER=air /go/bin/dlv exec ./tmp/main --headless=true --listen=:2345 --api-version=2 --accept-multiclient"

ただし、コード更新した場合、cosmtrek/airより自動ビルドされるが、vscode側が切断され、手動で再接続が必要です。
CleanShot 2020-09-27 at 16.22.58.png

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

docker centosでpython3をインストールする方法

はじめに

この記事ではAWSのAmazon Linux2を使用して次のことを実行します。
1. dockerのインストール
2. docker imageであるcentosを起動する
3. 2で起動したコンテナ内でpython3をインストール

1. dockerのインストール

まず以下のようにyumのアップデートを行います。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum update -y

次にdockerをインストールします。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo amazon-linux-extras install docker -y

インストールが完了したら、docker daemonを起動します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service docker start

ec2-userをdockerグループに追加します。
これは必須ではないですが、以降sudoなしでdockerコマンドが使用できます。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo usermod -a -G docker ec2-user

上記コマンドを実行したら、一度ターミナルを閉じます。その後再度接続し直します。

2. centosを起動する

まずrunコマンドによってコンテナを起動します。イメージのプルがされていない場合、プルをしてから起動することができます。
オプション-itにより、起動したコンテナの中に入ることができます。
(・・・は表示されるメッセージを省略して書いています)

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ docker run -it centos
・
・
・
[root@xxx /]#

3. コンテナ内でpython3をインストール

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ yum install python3 -y

以下のようにpython3コマンドを入力することで対話モードになり、インストールされたことがわかります。

[root@xxx /]# python3
Python 3.6.8 (default, Apr 16 2020, 01:36:27)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

インストール後はpip3コマンドを使用し、必要なパッケージのインストールを行うことができます。
次のコマンドでaws-cliのバージョン1をインストールしています。

[root@xxx /]# pip3 install awscli

参考記事

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

DockerでAzureKinectDKを動かそうと思ったらEULAに阻まれた件

DockerでBuildしようと思ったそのときに

よくわからんがDockerでROSを動かしてAzureKinectDKを動かそうを思いました。
ですがなんとまぁ謎の認証EULAくんの登場によって阻まれたのでした.

僕の環境

OS MacOS catalina 10.15.7
Docker Desktop 2.3.5

問題となった症状

Dockerfileにて

### 前略 ###
RUN sudo apt update && apt install k4a-tools libk4a1.4-dev
### 攻略 ###

としてDocker build .... をすると謎の文

Do you accept the EULA license terms? [yes/no] 

ときかれてyesを入力しても進まないという現象に見舞われました.

多分このパッケージのインストールに認証が必要なんでしょうねぇみたいに思ってinstallのオプションに-yを追加しましたが無事無視されニッチもサッチもビルドが進まないという感じになりました.

驚くほど簡単な解決法

問題となっているパッケージのインストール部分(今回で言えば k4a-tools libk4a1.4-devかな?)のコマンドを

RUN audo apt update && apt install ACCEPT_EULA=y k4a-tools link4a1.4-dev

ACCEPT_EULA=yをつけるだけでそのまま勝手に認証をしてくれます.

仮に他のパッケージのインストール時に出てきたとしてもこれつけとけばOKです.(多分)

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

Zenn CLI dockerで簡単構築

はじめに

Zenn は GitHubリポジトリと連携することで記事、本の管理がGitHubで行えるようになります。
またローカル環境を作成することでオンラインエディタではなく自分の好きなエディタを選ぶことが可能になります。
ローカル環境に色々と入れるのが面倒なので docker で簡単に構築できる環境を作成しました。

先に環境だけ欲しいという方はこちらを使用してください。

c-a-p-engineer/zenn-env

READE.ME を見て頂ければ使用方法を記載しております。

実行環境メモ

2020/09/26

  • Windows Pro 10
  • Docekr For Windows 2.3.0.5

フォルダ構成

フォルダ構成は以下の通りになります。

┣?articles # 記事ディレクトリ
┃ ┣?articles-1.md
┃ ┣?articles-2.md
┃ ┗?articles-3.md
┣?books # 本ディレクトリ
┃ ┗?book1
┃   ┣?1.md
┃   ┣?2.md
┃   ┣?config.yaml
┃   ┗?cover.png
┣?docker # Docker用ディレクトリ
┃ ┗?Dockerfile
┗?docker-compose.yml

Docker環境構築

Dockerを入れてない方はこちら → Docker

./docker/Dockerfile
FROM node:14

ENV NODE_PATH /opt/node_modules

WORKDIR /workspace

RUN apt-get -y update && apt-get install -y --no-install-recommends \
        git \
    && apt-get -y clean 

RUN npm init --yes \
    && npm install -g zenn-cli@latest \
    && npx zenn init
./docker-compose.yml
version: "3"

services:
  zenn:
    build:
      context: .
      dockerfile: docker/Dockerfile
    ports:
      - "8000:8000"
    volumes:
      - ".:/workspace"
    command: npx zenn preview

使い方

起動

docker-compose up

http://localhost:8000

記事の作成

docker exec -it zenn-env_zenn_1 zenn new:article

記事の中身 ./articles/{slug}.md

Zennのスラッグ(slug)とは

---
title: "" # 記事のタイトル
emoji: "?" # アイキャッチとして使われる絵文字(1文字だけ)
type: "tech" # tech: 技術記事 / idea: アイデア記事
topics: [] # タグ。["markdown", "rust", "aws"]のように指定する
published: true # 公開設定(falseにすると下書き)
---

ここから本文を書く

各種オプションの指定

zenn new:article --slug 記事のスラッグ --title タイトル --type idea --emoji ✨ 

記事の削除

削除はダッシュボードから行います。安全のため、articlesディレクトリからマークダウンファイルを削除してもzenn.dev上では削除はされません。

記事の削除

本の作成

docker exec -it zenn-env_zenn_1 zenn new:book
# 
# 本のslugを指定する場合は以下のようにします。
# docker exec -it zenn-env_zenn_1 zenn new:book new:book --slug ここにスラッグ

削除はダッシュボードから行います。安全のため、booksディレクトリからマークダウンファイルを削除してもzenn.dev上では削除はされません。
本の削除

プレビュー(docker起動時に自動実行)

docker exec -it zenn-env_zenn_1 zenn preview

最後に

完成画面はこちらのような感じになります。

Githubで管理・連携できる事からZennを使用してみようかと思います。

参考

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

【技術書まとめ】『Dockerを基本から学ぶ』を読んだまとめ

読んだ感想

コンパクトにまとまっていていいと思った。他の書籍で学習してから振り返りに読んでもいいかも。

気になったコマンドだけ備忘録

docker pull [イメージ名]  # イメージを取得する
docker run -d -p [ホスト側ポート]:[コンテナ側ポート][タグ名]
docker ps -a    # コンテナの状態を見る
docker stop [コンテナID]
  • データを永続化する
docker run -d -has -p 8081:80 -v $(PWD)/htdocs:/usr/local/apache2/htdocs/httpd
  • コンテナにログインする
docker exec -it コンテナID /bin/bash
  • docker-composeコンテナ起動
docker-compose up -d
docker-compose ps -a
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Docker+WordPress+MySQL]で画像投稿できるようにする

はい、はるうさぎです。
今回はお仕事でWordPress案件をいただいて、詰まったことがあったのでメモ書きです。
普段からWordPressを触っている人はご存知だと思う内容かと思います。

前提

  • dockerでWordPress環境を構築する
  • その環境下でテーマ作成

今回詰まったところ

  • dockerでWordPress環境を構築したら、WordPressで画像をアップロードできない
  • そもそもコンテナが立ち上がらない

順番に見ていきます。
まずディレクトリ構造

wp-template
├── docker-compose.yml
├── wp-config.php
└── wp-content
    ├── index.php
    ├── languages
    ├── plugins
    ├── themes
    ├── upgrade
    └── uploads

最悪、docker-compose.ymlwp-contentフォルダがあれば動きます。
wp-contentの中身はdocker-compose upすれば自動的に初期のものが構成されます。
wp-config.phpはWordPressには必須ファイルです。インストール時に自動生成してくれる?みたいなのですが、私の場合してくれなかったので公式wp-config.phpを参考に変更しました。

docker-compose.yml
version: "3"

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress #任意
      MYSQL_DATABASE: wordpress #任意
      MYSQL_USER: wordpress #任意
      MYSQL_PASSWORD: wordpress #任意

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306 
      WORDPRESS_DB_USER: wordpress #任意
      WORDPRESS_DB_PASSWORD: wordpress #任意
    volumes:
      - ./wp-content:/var/www/html/wp-content
      - ./wp-config.php:/var/www/html/wp-config.php
volumes:
  db_data:

DB関連は.envで管理した方が楽だと書きながら思いました。
これでhttp://localhost:8000/にアクセスするとWordPressの見慣れた画面が出てきます。

ここまでが普通にできること。

dockerでWordPress環境を構築したら、WordPressで画像をアップロードできない

WordPressで投稿を行う為に画像をアップロードしようと思ったらできない!
調べてみると、wp-config.phpにある一文を追記しないといけないみたいです。

wp-config.php
define('DB_NAME', 'wordpress'); #docker-compose.ymlで設定したもの
define('DB_USER', 'wordpress'); #docker-compose.ymlで設定したもの
define('DB_PASSWORD', 'wordpress'); #docker-compose.ymlで設定したもの

define('DB_HOST', 'db'); #docker-compose.ymlで定義したmysqlコンテナ名
define('WP_DEBUG', true);
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');
define('UPLOADS', 'wp-content/uploads' ); #これを追記

$table_prefix = 'wp_';

if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

require_once(ABSPATH . 'wp-settings.php');

これが最終形態なコード。
以下を追記する必要があったコード。

define('UPLOADS', 'wp-content/uploads' );

そもそもコンテナが立ち上がらない

sed: cannot rename ./xxxxx Device or resource busyと表示されてコンテナが立ち上がらない。
調べると以下の記事が出てきた。これで解決。先人の知恵は素晴らしい。
https://qiita.com/suzukihi724/items/e56fa9516639c6c90a33

おわりに

学生の頃からWordPressを触っていましたが、MAMP環境だったので難しいことはありませんでした。
今回はdockerで環境構築だったので、WordPressの奥深いところを理解できたのではないか、そう思いました。
普段から触っている方には普通の内容だったかと思います。。。

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

[Docker+WordPress+MySQL]環画像投稿できるようにする

はい、はるうさぎです。
今回はお仕事でWordPress案件をいただいて、詰まったことがあったのでメモ書きです。
普段からWordPressを触っている人はご存知だと思う内容かと思います。

前提

  • dockerでWordPress環境を構築する
  • その環境下でテーマ作成

今回詰まったところ

  • dockerでWordPress環境を構築したら、WordPressで画像をアップロードできない
  • そもそもコンテナが立ち上がらない

順番に見ていきます。
まずディレクトリ構造

wp-template
├── docker-compose.yml
├── wp-config.php
└── wp-content
    ├── index.php
    ├── languages
    ├── plugins
    ├── themes
    ├── upgrade
    └── uploads

最悪、docker-compose.ymlwp-contentフォルダがあれば動きます。
wp-contentの中身はdocker-compose upすれば自動的に初期のものが構成されます。
wp-config.phpはWordPressには必須ファイルです。インストール時に自動生成してくれる?みたいなのですが、私の場合してくれなかったので公式wp-config.phpを参考に変更しました。

docker-compose.yml
version: "3"

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress #任意
      MYSQL_DATABASE: wordpress #任意
      MYSQL_USER: wordpress #任意
      MYSQL_PASSWORD: wordpress #任意

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306 
      WORDPRESS_DB_USER: wordpress #任意
      WORDPRESS_DB_PASSWORD: wordpress #任意
    volumes:
      - ./wp-content:/var/www/html/wp-content
      - ./themes/wp-template:/var/www/html/wp-content/themes/wp-template #今回作成依頼のテーマ
      - ./wp-config.php:/var/www/html/wp-config.php
volumes:
  db_data:

DB関連は.envで管理した方が楽だと書きながら思いました。
これでhttp://localhost:8000/にアクセスするとWordPressの見慣れた画面が出てきます。

ここまでが普通にできること。

dockerでWordPress環境を構築したら、WordPressで画像をアップロードできない

WordPressで投稿を行う為に画像をアップロードしようと思ったらできない!
調べてみると、wp-config.phpにある一文を追記しないといけないみたいです。

wp-config.php
define('DB_NAME', 'wordpress'); #docker-compose.ymlで設定したもの
define('DB_USER', 'wordpress'); #docker-compose.ymlで設定したもの
define('DB_PASSWORD', 'wordpress'); #docker-compose.ymlで設定したもの

define('DB_HOST', 'db'); #docker-compose.ymlで定義したmysqlコンテナ名
define('WP_DEBUG', true);
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');
define('UPLOADS', 'wp-content/uploads' ); #これを追記

$table_prefix = 'wp_';

if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

require_once(ABSPATH . 'wp-settings.php');

これが最終形態なコード。
以下を追記する必要があったコード。

define('UPLOADS', 'wp-content/uploads' );

そもそもコンテナが立ち上がらない

sed: cannot rename ./xxxxx Device or resource busyと表示されてコンテナが立ち上がらない。
調べると以下の記事が出てきた。これで解決。先人の知恵は素晴らしい。
https://qiita.com/suzukihi724/items/e56fa9516639c6c90a33

おわりに

学生の頃からWordPressを触っていましたが、MAMP環境だったので難しいことはありませんでした。
今回はdockerで環境構築だったので、WordPressの奥深いところを理解できたのではないか、そう思いました。
普段から触っている方には普通の内容だったかと思います。。。

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

【PHP】TCPDF + FPDIでPDFを出力してみた話

はじめに

タイトルの通りですが
TCPDFFPDIのライブラリを使用して、PDFを出力してみました。
今回はコマンドラインから実行してみます。

本編

環境構築

お好みでPHP、Composerが使用できる環境を用意してください。

Docker

今回私が使用したDocker環境は以下です(一部割愛)。

./docker-compose.yml
version: '3'
services:
 php:
   build: ./php
   volumes:
     - ./work:/home/work
./php/dockerfile
FROM php:7.3-fpm
COPY php.ini /usr/local/etc/php/

# Composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('sha384', 'composer-setup.php') === '795f976fe0ebd8b75f26a6dd68f78fd3453ce79f32ecb33e7fd087d39bfeb978342fb73ac986cd4f54edd0dc902601dc') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \
  && mv composer.phar /usr/local/bin/composer
./php/php.ini
date.timezone = "Asia/Tokyo"

Composer

立ち上げが完了したらphpのコンテナへ入り、
Composerでライブラリのインストールを行います。

また、ライブラリの他にautoloadの記載も追加しています。

/home/work/src/composer.json
{
    "require": {
        "setasign/fpdi": "^2.3",
        "tecnickcom/tcpdf": "^6.3"
    },

    "autoload": {
        "psr-4": {
            "Classes\\" : "classes/"
        }
    }
}

インストールが終われば完了です。

# cd /home/work/src
# composer install

実装

ファイル構成

# cd /home/work/

# ls /home/work/output/pdf/fileYYYYmmdd-HHiiss #PDF出力ファイル
# ls /home/work/src/resources/font/ipam.ttf #フォントの格納先
# ls /home/work/src/resources/pdf/templete.pdf #PDFテンプレートの格納先
# ls /home/work/bin/make-pdf.php #コマンドラインで実行するソース
# ls /home/work/src/bootstrap.php # 起動用ファイル(割愛)
# ls /home/work/src/classes/MyTcpdf.php # TCPDF利用クラス
# ls /home/work/src/classes/common/DynamicProperty.php # 動的クラス(割愛)
# ls /home/work/src/classes/MyTcpdf/FontColor.php # フォントカラークラス(割愛)

テンプレート

至ってシンプルなPDFテンプレートファイルです。

image.png

ソース

/home/work/bin/make-pdf.php
<?php

require_once __DIR__ . '/../src/bootstrap.php';

use Classes\MyTcpdf;
use Classes\MyTcpdf\FontColor;

// テンプレートを使用せずに出力
$myTcpdf = new MyTcpdf();
$myTcpdf->addPage();
$myTcpdf->setText('テンプレートを使用せずに出力', 10, 20, new FontColor(0, 255, 0));
$myTcpdf->outputPdfFile();

// テンプレートを使用して出力
$myTcpdfTmp = new MyTcpdf();
$myTcpdfTmp->addPageWithTemplete(1);
$myTcpdfTmp->setText('テンプレートを使用して出力', 10, 20, new FontColor(255, 0, 0));
$myTcpdfTmp->outputPdfFile();
/home/work/src/classes/MyTcpdf.php
<?php

namespace Classes;

use TCPDF_FONTS;
use setasign\Fpdi\Tcpdf\Fpdi;
use Classes\MyTcpdf\FontColor;

class MyTcpdf
{
    // 出力ファイル
    const OUTPUT_FORMAT_CHAR = 'F';
    const OUTPUT_FILE_DIR = __DIR__.'/../../output/pdf/';
    const OUTPUT_FILE_NAME = 'file';

    // PDF
    const PDF_ORIENTATION = 'P';
    const PDF_UNIT = 'mm';
    const PDF_SIZE = 'A4';
    const PDF_TEMPLETE = __DIR__.'/../resources/pdf/templete.pdf';

    // フォントファイル
    const FONT_FILE_NAME = __DIR__.'/../resources/font/ipam.ttf';

    /**
     * コンストラクタ
     */
    public function __construct()
    {
        $this->fpdi = new Fpdi(self::PDF_ORIENTATION, self::PDF_UNIT, self::PDF_SIZE);
        $this->fpdi->SetMargins(0, 0, 0);
        $this->fpdi->SetFont($this->getFont(), '', 32);
    }

    /**
     * 出力文字を設定する
     * @param _text 文字列
     * @param _x X座標
     * @param _y Y座標
     * @param _h 高さ
     */
    public function setText(string $_text, int $_x, int $_y, FontColor $_fontColor, int $_h = 0)
    {
        $this->fpdi->SetTextColor($_fontColor->R, $_fontColor->G, $_fontColor->B);
        $this->fpdi->SetXY($_x, $_y);
        $this->fpdi->Write($_h, $_text);
    }

    /**
     * 追加するフォントを取得する
     */
    private function getFont()
    {
        return TCPDF_FONTS::addTTFfont(self::FONT_FILE_NAME);
    }

    /**
     * 出力するファイル名を取得する
     * @return string ファイル名
     */
    private function getOutputFilename()
    {
        return self::OUTPUT_FILE_DIR . self::OUTPUT_FILE_NAME . date("Ymd-His"). '.pdf';
    }

    /**
     * ページを追加する
     */
    public function addPage()
    {
        $this->fpdi->AddPage();
    }

    /**
     * テンプレートベースのページを追加する
     */
    public function addPageWithTemplete($_pageNum)
    {
        $this->fpdi->SetSourceFile(self::PDF_TEMPLETE);
        $page = $this->fpdi->importPage($_pageNum);
        $this->fpdi->AddPage();
        $this->fpdi->useTemplate($page, null, null, null, null, true);
    }

    /**
     * PDFファイル出力
     */
    public function outputPdfFile()
    {
        $this->fpdi->Output(
            $this->getOutputFilename(),
            self::OUTPUT_FORMAT_CHAR
        );
    }
}

実行コマンド

php /home/work/bin/make-pdf.php

実行結果

以下のようにファイルが出力された。

テンプレートなし テンプレートあり
image.png image.png

終わりに

PDFのテンプレートの上に文字を出力できるので、フォーマットを変えずに必要な情報だけを出力できますね。
勤務表や請求書・領収書など、特定の部分だけが変動するファイルに活用できそう。

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

PHPのTCPDF + FPDIでPDFを出力してみた話

はじめに

タイトルの通りですが
TCPDFFPDIのライブラリを使用して、PDFを出力してみました。
今回はコマンドラインから実行してみます。

本編

環境構築

お好みでPHP、Composerが使用できる環境を用意してください。

Docker

今回私が使用したDocker環境は以下です(一部割愛)。

./docker-compose.yml
version: '3'
services:
 php:
   build: ./php
   volumes:
     - ./work:/home/work
./php/dockerfile
FROM php:7.3-fpm
COPY php.ini /usr/local/etc/php/

# Composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('sha384', 'composer-setup.php') === '795f976fe0ebd8b75f26a6dd68f78fd3453ce79f32ecb33e7fd087d39bfeb978342fb73ac986cd4f54edd0dc902601dc') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \
  && mv composer.phar /usr/local/bin/composer
./php/php.ini
date.timezone = "Asia/Tokyo"

Composer

立ち上げが完了したらphpのコンテナへ入り、
Composerでライブラリのインストールを行います。

また、ライブラリの他にautoloadの記載も追加しています。

/home/work/src/composer.json
{
    "require": {
        "setasign/fpdi": "^2.3",
        "tecnickcom/tcpdf": "^6.3"
    },

    "autoload": {
        "psr-4": {
            "Classes\\" : "classes/"
        }
    }
}

インストールが終われば完了です。

# cd /home/work/src
# composer install

実装

ファイル構成

# cd /home/work/

# ls /home/work/output/pdf/fileYYYYmmdd-HHiiss #PDF出力ファイル
# ls /home/work/src/resources/font/ipam.ttf #フォントの格納先
# ls /home/work/src/resources/pdf/templete.pdf #PDFテンプレートの格納先
# ls /home/work/bin/make-pdf.php #コマンドラインで実行するソース
# ls /home/work/src/bootstrap.php # 起動用ファイル(割愛)
# ls /home/work/src/classes/MyTcpdf.php # TCPDF利用クラス
# ls /home/work/src/classes/common/DynamicProperty.php # 動的クラス(割愛)
# ls /home/work/src/classes/MyTcpdf/FontColor.php # フォントカラークラス(割愛)

テンプレート

至ってシンプルなPDFテンプレートファイルです。

image.png

ソース

/home/work/bin/make-pdf.php
<?php

require_once __DIR__ . '/../src/bootstrap.php';

use Classes\MyTcpdf;
use Classes\MyTcpdf\FontColor;

// テンプレートを使用せずに出力
$myTcpdf = new MyTcpdf();
$myTcpdf->addPage();
$myTcpdf->setText('テンプレートを使用せずに出力', 10, 20, new FontColor(0, 255, 0));
$myTcpdf->outputPdfFile();

// テンプレートを使用して出力
$myTcpdfTmp = new MyTcpdf();
$myTcpdfTmp->addPageWithTemplete(1);
$myTcpdfTmp->setText('テンプレートを使用して出力', 10, 20, new FontColor(255, 0, 0));
$myTcpdfTmp->outputPdfFile();
/home/work/src/classes/MyTcpdf.php
<?php

namespace Classes;

use TCPDF_FONTS;
use setasign\Fpdi\Tcpdf\Fpdi;
use Classes\MyTcpdf\FontColor;

class MyTcpdf
{
    // 出力ファイル
    const OUTPUT_FORMAT_CHAR = 'F';
    const OUTPUT_FILE_DIR = __DIR__.'/../../output/pdf/';
    const OUTPUT_FILE_NAME = 'file';

    // PDF
    const PDF_ORIENTATION = 'P';
    const PDF_UNIT = 'mm';
    const PDF_SIZE = 'A4';
    const PDF_TEMPLETE = __DIR__.'/../resources/pdf/templete.pdf';

    // フォントファイル
    const FONT_FILE_NAME = __DIR__.'/../resources/font/ipam.ttf';

    /**
     * コンストラクタ
     */
    public function __construct()
    {
        $this->fpdi = new Fpdi(self::PDF_ORIENTATION, self::PDF_UNIT, self::PDF_SIZE);
        $this->fpdi->SetMargins(0, 0, 0);
        $this->fpdi->SetFont($this->getFont(), '', 32);
    }

    /**
     * 出力文字を設定する
     * @param _text 文字列
     * @param _x X座標
     * @param _y Y座標
     * @param _h 高さ
     */
    public function setText(string $_text, int $_x, int $_y, FontColor $_fontColor, int $_h = 0)
    {
        $this->fpdi->SetTextColor($_fontColor->R, $_fontColor->G, $_fontColor->B);
        $this->fpdi->SetXY($_x, $_y);
        $this->fpdi->Write($_h, $_text);
    }

    /**
     * 追加するフォントを取得する
     */
    private function getFont()
    {
        return TCPDF_FONTS::addTTFfont(self::FONT_FILE_NAME);
    }

    /**
     * 出力するファイル名を取得する
     * @return string ファイル名
     */
    private function getOutputFilename()
    {
        return self::OUTPUT_FILE_DIR . self::OUTPUT_FILE_NAME . date("Ymd-His"). '.pdf';
    }

    /**
     * ページを追加する
     */
    public function addPage()
    {
        $this->fpdi->AddPage();
    }

    /**
     * テンプレートベースのページを追加する
     */
    public function addPageWithTemplete($_pageNum)
    {
        $this->fpdi->SetSourceFile(self::PDF_TEMPLETE);
        $page = $this->fpdi->importPage($_pageNum);
        $this->fpdi->AddPage();
        $this->fpdi->useTemplate($page, null, null, null, null, true);
    }

    /**
     * PDFファイル出力
     */
    public function outputPdfFile()
    {
        $this->fpdi->Output(
            $this->getOutputFilename(),
            self::OUTPUT_FORMAT_CHAR
        );
    }
}

実行コマンド

php /home/work/bin/make-pdf.php

実行結果

以下のようにファイルが出力された。

テンプレートなし テンプレートあり
image.png image.png

終わりに

PDFのテンプレートの上に文字を出力できるので、フォーマットを変えずに必要な情報だけを出力できますね。
勤務表や請求書・領収書など、特定の部分だけが変動するファイルに活用できそう。

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

VSCodeのRemote-ContainersでFlaskをやってみた

概要

VSCodeのRemote-Containersという拡張機能で、DockerコンテナにPython環境を作って、あれこれできるので、そのメモです。

Dockerコンテナを使う目的

目的は2つあります。

1つ目は、ローカル環境が汚れない。
pyenv、anacondaなど環境を切り替えるものはありますが、結局ローカル依存になります。requirementsを作っても、Pythonのバージョンは?とか、コマンドなんだっけとか、なぜか入らないとか、pipとcondaは混ぜちゃいけないとか、たまになんかわからないけど全部ふっとんだりするので、もう卒業したいという気分です。

2つ目は、デプロイが楽。
近頃は、ローカルPC上でなくクラウド上で計算したり、サービスを提供したりすることがあるので、それもDockerfileでて数少なくでやりたいです。

そういうわけで、すぐにこれらを得られるわけではありませんが、この記事では、Remote-ContainerでFlaskを立てるところまで記録します。

最初に結果

最終的にできたファイルはgithubに置いておきました。
yo16 / simple_flask

最終的なファイル構成.
/simple_flask
    /.devcontainer
        Dockerfile
        devcontainer.json
    /simple_app
        /templates
            default.html
        app.py
    requirements.txt

けどこの記事では、作った結果や中身を伝えたいわけではなく、VSCodeでの手順なので、あまり関係ないかな。Flaskのシンプルなソースを作るのがめんどくさい人はダウンロードしてご使用くださいw

手順0:フォルダを準備

今回の環境を作るためのフォルダを作ります。今回は「simple_flask」。

ここまででのファイル構成.
/simple_app

手順1:Flaskを準備

まーなんでもいいので単純なものを作ります。

ここまででのファイル構成.
/simple_flask
    /simple_app
        /templates
            default.html
        app.py

Flaskの内容の説明はしませんが、app.pyにapp.run()とか@app.route('/')とか書いてあります。これをpython app.pyするとFlaskのサイトが立ち上がります。

手順2:VSCodeで開き、Docker-Containersを準備

  1. トップの/simple_flaskフォルダをVSCodeで開く
  2. 左のツールバーの機能拡張で、「remote-containers」を検索
  3. インストール

20200926_2.PNG

手順3:Docker環境を作る

  1. VSCodeの左下の><みたいな緑のところをクリック
  2. 画面上に出てきたものから、「Remote-Containers: Open Folder in Container...」を選択
    20200926_4.PNG

  3. 「simple_flask」のフォルダを選択してOpen

  4. また上に出てくるので「Python 3」を選択
    20200926_5.PNG

  5. また出てくるので適切なPythonバージョンを選択
    20200926_6.PNG

  6. また出てくるのでOK(これが最後)
    ちなみにここでチェックオフにして、0個選択済み になっても、なんかインストールされることになるのであとの手順で確認します。
    20200926_7.PNG

  7. ここまでできると、下記のような画面になります。
    ポイントは、右下のターミナルのところで、linuxっぽい画面になってます。(ほんとうにそうなんだけど)
    ここはもう、Dockerコンテナに入ってbashを起動した状態になってます。
    20200926_8.png

なのでそこでlsしてみるとこんな感じで、「simple_app」もしっかり置かれています。

root@c249cd5c6b06:/workspaces/simple_flask# ls -la
total 4
drwxrwxrwx 1 root root 4096 Sep 26 14:49 .
drwxr-xr-x 3 root root 4096 Sep 26 13:54 ..
drwxrwxrwx 1 root root 4096 Sep 26 14:49 .devcontainer
drwxrwxrwx 1 root root 4096 Sep 26 14:08 simple_app

Pythonも入ってます。

root@c249cd5c6b06:/workspaces/simple_flask# python -V
Python 3.8.5

手順4:Flaskをインストール

手順3の4でpythonのDockerイメージを選択しているので、Pythonは入っているものの、素の状態なので当然Flaskはありません。なので入れます。
これはまず、先ほどのコンソール上で入れます。

root@c249cd5c6b06:/workspaces/simple_flask# pip install flask
Requirement already satisfied: flask in /usr/local/lib/python3.8/site-packages (1.1.2)
Requirement already satisfied: Werkzeug>=0.15 in /usr/local/lib/python3.8/site-packages (from flask) (1.0.1)
Requirement already satisfied: click>=5.1 in /usr/local/lib/python3.8/site-packages (from flask) (7.1.2)
Requirement already satisfied: itsdangerous>=0.24 in /usr/local/lib/python3.8/site-packages (from flask) (1.1.0)
Requirement already satisfied: Jinja2>=2.10.1 in /usr/local/lib/python3.8/site-packages (from flask) (2.11.2)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.8/site-packages (from Jinja2>=2.10.1->flask) (1.1.1)

あれ、入ってる・・・(汗
ま、まぁ他の物を入れたいこともあると思うので、その場合はこの手順で、ということで、入っていなかったテイで進めますね~。

つぎに、今入っているモジュールを、Dockerコンテナが作られたときに自動的にインストールしてもらうために、requirements.txtを作ります。

root@c249cd5c6b06:/workspaces/simple_flask# pip freeze > requirements.txt

こうすると、当然Dockerコンテナの中にはできると思うのだけれど、VSCode上でもできます。
VSCodeで普通に開いて確認、編集ができます。

20200926_9.PNG

これを次の手順で使います。

手順5:Dockerfileの確認と修正

コンテナを作成する際に動いているのが、./dockercontainer/Dockerfileです。

このファイルをVSCodeで開いてみると、Dockerコンテナを開くときに動くものがいろいろわかります。(microsoftのイメージを使ってるんだなーとか。)

ここで、手順2の6で説明した、Node.jsをインストールするかしないか、選択してもしなくても、インストールすることになっているので、その辺りをコメントアウトして、nodejsは使わないようにしちゃいます。この記事の単純なFlaskではいらないのですが、必要な人は使ってください。

また逆に、手順4で作ったrequirements.txtは使われていないので、コメントを外します。/tmp/pip-tmp/へコピーして、pip installして、終わったら消してますね。

手を加えたDockerfileが下記です。

# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/python-3/.devcontainer/base.Dockerfile

# [Choice] Python version: 3, 3.8, 3.7, 3.6
ARG VARIANT="3"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

# [Option] Install Node.js
#### comment out
# ARG INSTALL_NODE="true"
# ARG NODE_VERSION="lts/*"
# RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
#### removed "#"
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
   && rm -rf /tmp/pip-tmp

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
#     && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

手順6:もう一度Dockerコンテナを起動

変更したDockerfileを使って、もう一度コンテナを作り直します。

  1. 左下の緑のところをクリック
    20200926_10.PNG

  2. 上のプルダウンから「Remote-Containers: Rebuild Container」を選択
    20200926_11.PNG

これですべて完了!お疲れさまでした。

動作確認

右下のターミナルからpythonでapp.pyを起動すると、いつものFlaskサーバーが立ち上がります。

root@acebfd6333f5:/workspaces/simple_flask# python ./simple_app/app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

以上ですー

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