- 投稿日:2020-09-27T22:18:55+09:00
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.ioInstall 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-composeno sudo
- sudo 無しで実行可能とする
sudo groupadd docker sudo gpasswd -a $USER dockerdocker 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
- 投稿日:2020-09-27T22:18:47+09:00
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]: jsoncertsディレクトリに移動し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.keyALBはVPC内にサブネットが2つ必要です。それらを作り終えたらEC2のコンソール画面に移動し、ロードバランサーをクリックします。
ALBを選択します。
VPCの選択では先ほど作成したVPC、サブネットを選択します。
デフォルトの証明書の選択では、アップロードした証明書を選択します。ターゲットの登録では、選択したサブネット内のEC2をターゲットグループに登録できます。
以下のメッセージにより正常に作成されたかどうかを確認します。参考記事
- OpenSSL でサーバ証明書の作成
https://rfs.jp/server/setting/ssl-openssl.html- 四苦八苦しながらELBにSSL証明書をアップロードした話
https://www.simpline.co.jp/tech/%E5%9B%9B%E8%8B%A6%E5%85%AB%E8%8B%A6%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89elb%E3%81%ABssl%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%81%9F/
- 投稿日:2020-09-27T20:51:51+09:00
PyTorch+GPUをDockerで実装
はじめに
最近やっとDockerを使い始めました。
Dockerを使えば、いろんなPCでお手軽に深層学習できます。環境(ホスト)
OS:Ubuntu 20.04
GPU:NVIDIA GeForce GTX 1080GPUドライバをインストール
まず、ホストで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 dockerDockerfile
Dockerfileには仮想環境をどのようにするかを記述します。
1行目の FROM の部分でベースの環境を変更できます。(Ubuntu や CUDA のバージョンや cudnn の有無など)
nvidia/cuda の DockerHub を調べるといろいろ出てきます。(https://hub.docker.com/r/nvidia/cuda/tags)
また RUN の3行目で Python のライブラリを選択できます。DockerfileFROM 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.pyfrom __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って便利ですね(笑)
- 投稿日:2020-09-27T20:00:10+09:00
Docker関連コマンド(自分用の備忘メモ)
- 投稿日:2020-09-27T18:07:18+09:00
[Laravel] プロジェクト開始までの忘備録
概要
Laravel プロジェクトを開始するまでのコマンドをまとめた個人メモ。
前提条件
- MacOS
- Composer, Laravel インストールされている
- Docker がインストールされている
プロジェクトの開始
Version6系を使用し、
tasklist
というプロジェクト名で作成する$ composer create-project --prefer-dist laravel/laravel tasklist ^6.0DB作成
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=mysqlDB接続の確認
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 }
- 投稿日:2020-09-27T18:07:18+09:00
[Laravel] プロジェクト開始までのコマンド忘備録
概要
Laravel プロジェクトを開始するまでのコマンドをまとめた個人メモ。
前提条件
- MacOS
- Composer, Laravel インストールされている
- Docker がインストールされている
プロジェクトの開始
Version6系を使用し、
tasklist
というプロジェクト名で作成する$ composer create-project --prefer-dist laravel/laravel tasklist ^6.0DB作成
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=mysqlDB接続の確認
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 }
- 投稿日:2020-09-27T17:25:37+09:00
.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されないファイルも含まれます。ビルドコンテキスト以下の全てのファイルが含まれるのです。.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ファイル以下の階層であれば、どの階層であっても無視されます。
例えば、
.gitignoretargetと記載すると、
target src/target path/a/b/targetなどが無視されます。
.dockerignore
.dockerignoreでは、パスはすべて.dockerignoreが置かれているパスからの相対パスで記載します。1
例えば、
.dockerignoretargetと記載すると、
targetのみが無視され、
src/target path/a/b/targetは無視されません。
.gitignoreのように任意の階層を対象にしたい場合は
dockerignore**/targetと記載します。
サブディレクトリにあるignorefile
.gitignore
.gitignoreの場合、.gitignoreをサブディレクトリにも配置することができます。その場合は対象ファイルに近い方のルールが優先されます。
.dockerignore
.dockerignoreはビルドコンテキストルートにある.dockerignoreしか読み込まれません。サブディレクトリにある.dcokerignoreファイルは読み込まれません。
Dockerfileのディレクトリとビルドコンテキストが異なる場合に注意が必要です。Dockerfileと同じ場所に.gitignoreを置くのではなく、ビルドコンテキストに.dockerignoreを配置します。
あとがき
もしかしてもう少し違いがあるかもしれませんが、今のところ見つけた違いはこのくらいでした。
快適なdockerライフを。環境
- Docker: 19.03.12
- Docker for Mac: 2.3.0.5
参考資料リンク
- Dockerfile リファレンス — Docker-docs-ja 17.06 ドキュメント#dockerignore-file
- build — Docker-docs-ja 17.06 ドキュメント#dockerignor
- Dockerfile 記述のベストプラクティス | Docker ドキュメント#ビルドコンテキストの理解
- Docker Buildにおけるリードタイム短縮のための3つの改善ポイント | PLAID engineer blog
- docker-compose で一向にビルドがはじまらない、もしくは起動しない。はたまた忘れたころに起動する。 - Qiita
.gitignoreと同様にパスの先頭に
/
を付けることも可能です。 ↩
- 投稿日:2020-09-27T17:24:29+09:00
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 コンテナ内の作業ディレクトリ
- 投稿日:2020-09-27T17:11:04+09:00
Clean My Mac Xを使った後にDockerが使えなくなった事件
この記事について
MacOSをアップデートしようと思ったのですが、ストレージが「その他」でいっぱいになり、いらないファイルやらを消してくれる「Clean My Mac X」を使用して、Macの再起動後にDocekrを立ち上げようとすると、添付画像のエラーが表示されました。
今回はこのエラーを解決するためにやったことをまとめた記事です。
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をアップデートすると、ちゃんと使えるようになっていました!
反省
バージョンいくつか試してうまくいかないようならそもそもシステム周りのファイルを消された可能性があったから、無闇に削除するとえらい目に合っちゃう。。。
- 投稿日:2020-09-27T16:48:51+09:00
Redmineのコードリーディング環境をDockerで構築する
概要
redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。
- redmineのmasterブランチのコードがDocker上で動作する
- Debug用のツールが使える
モチベーション
動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。
なぜコードリーディングしたいのか?
人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。なぜRedmineか?
Redmineを選んだのは以下の理由です。
- 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
- 長年メンテナンスされており、世界中で使用されている。
- 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。
環境構築
以下を参考にすすめていきます。
リポジトリの用意
- redmineのレポジトリをフォーク
- フォークしたリポジトリをクローン
redmine
ディレクトリに移動- 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がインストールされます。DockerfileFROM 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.ymlversion: '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の追記
- 【Rails】better_errorsとbinding_of_callerで自分でエラーを解決できるようになろう【初心者向け】 - Qiita
- pry-byebugでrubyをデバッグする - Qiita
などの記事を参考にGemfile.に以下を追加します。
- better_errors
- binding_of_caller
- pry-rails
- pry-byebug
Gemfilegroup :development do gem "yard" #この下に追記する gem "better_errors" gem "binding_of_caller" gem "pry-rails" gem "pry-byebug" # 安定動作しなかったのでコメントアウト # gem "ruby-debug-ide" # gem "debase" enddatabase.ymlの設定
config/database.yml
を作成し以下の内容にします。config/database.ymldefault: &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.rbBetterErrors::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.rbdef 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を終了
以上
- 投稿日:2020-09-27T16:48:51+09:00
Redmineのコードリーディング環境をDocker上に構築する
概要
redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。
- redmineのmasterブランチのコードがDocker上で動作する
- Debug用のツールが使える
モチベーション
動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。
なぜコードリーディングしたいのか?
人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。なぜRedmineか?
Redmineを選んだのは以下の理由です。
- 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
- 長年メンテナンスされており、世界中で使用されている。
- 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。
環境構築
以下を参考にすすめていきます。
リポジトリの用意
- redmineのレポジトリをフォーク
- フォークしたリポジトリをクローン
redmine
ディレクトリに移動- 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を動的に変えるという発想があまりなかったので既に学びがあったと感じています。DockerfileFROM 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.ymlversion: '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の追記
- 【Rails】better_errorsとbinding_of_callerで自分でエラーを解決できるようになろう【初心者向け】 - Qiita
- pry-byebugでrubyをデバッグする - Qiita
などの記事を参考にGemfile.に以下を追加します。
- better_errors
- binding_of_caller
- pry-rails
- pry-byebug
Gemfilegroup :development do gem "yard" #この下に追記する gem "better_errors" gem "binding_of_caller" gem "pry-rails" gem "pry-byebug" # 安定動作しなかったのでコメントアウト # gem "ruby-debug-ide" # gem "debase" enddatabase.ymlの設定
config/database.yml
を作成し以下の内容にします。config/database.ymldefault: &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.rbBetterErrors::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.rbdef 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を終了
以上
- 投稿日:2020-09-27T16:48:51+09:00
Redmineのコードリーディング用環境をDocker上に構築する
概要
redmineのソースコードを読むための環境をDockerで構築します。以下の状態をゴールとします。
- redmineのmasterブランチのコードがDocker上で動作する
- Debug用のツールが使える
モチベーション
動作環境を構築するのは実際のアプリケーションの挙動とコード内容を頭の中で紐付けながらコードリーディングしたいからです。
なぜコードリーディングしたいのか?
人が書いたコードを読むことは新たな発見や学びに繋がると考えています。
私の場合は、クラスの分け方、命名、テストコードの書き方、エラーハンドリングの仕方などに悩むことが最近多いので、そのあたりの引き出しを増やしたいというモチベーションがあります。なぜRedmineか?
Redmineを選んだのは以下の理由です。
- 普段からRedmineを使っているため馴染みがあり、画面や外部仕様をある程度知っている。
- 長年メンテナンスされており、世界中で使用されている。
- 普段はPHPをつかっているため、あえて別の言語やFWに触れてみる。
環境構築
以下を参考にすすめていきます。
リポジトリの用意
- redmineのレポジトリをフォーク
- フォークしたリポジトリをクローン
redmine
ディレクトリに移動- 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を動的に変えるという発想があまりなかったので既に学びがあったと感じています。DockerfileFROM 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.ymlversion: '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の追記
- 【Rails】better_errorsとbinding_of_callerで自分でエラーを解決できるようになろう【初心者向け】 - Qiita
- pry-byebugでrubyをデバッグする - Qiita
などの記事を参考にGemfile.に以下を追加します。
- better_errors
- binding_of_caller
- pry-rails
- pry-byebug
Gemfilegroup :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.rbBetterErrors::Middleware.allow_ip! "0.0.0.0/0"database.ymlの設定
config/database.yml
を作成し以下の内容にします。config/database.ymldefault: &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.rbdef 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を終了
以上
- 投稿日:2020-09-27T16:32:47+09:00
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にする
.zshrcexport GO111MODULE=on
- Go Modulesの初期化
/src$ go mod init パッケージ名
ディレクトリ構成
Ginのディレクトリ構成は特に決まってないので、以下は自己流です。
メインのソースコードは全部srcの下に配置する。今後はmodels
やcontrollers
もsrcに追加する予定です。. ├── .vscode │ └── launch.json ├── docker │ ├── go │ │ └── Dockerfile │ └── mysql │ └── Dockerfile ├── src │ ├── go.mod │ ├── go.sum │ ├── .air.toml │ └── main.go │ └── docker-compose.ymlDocker
Go
/docker/go/DockerfileFROM 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.tomlMySQL
/docker/go/DockerfileFROM mysql:8.0 RUN chown -R mysql /var/lib/mysql && \ chgrp -R mysql /var/lib/mysqldocker-compose
./docker-compose.ymlversion: '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: - backendcosmtrek/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側が切断され、手動で再接続が必要です。
- 投稿日:2020-09-27T16:25:11+09:00
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 startec2-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参考記事
- AWS 公式サイト https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html
- CentOS7 に pip と awscli をインストール https://rriifftt.hatenablog.com/entry/2015/10/28/142043
- 投稿日:2020-09-27T15:39:50+09:00
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-devACCEPT_EULA=yをつけるだけでそのまま勝手に認証をしてくれます.
仮に他のパッケージのインストール時に出てきたとしてもこれつけとけばOKです.(多分)
- 投稿日:2020-09-27T14:32:35+09:00
Zenn CLI dockerで簡単構築
はじめに
Zenn は GitHubリポジトリと連携することで記事、本の管理がGitHubで行えるようになります。
またローカル環境を作成することでオンラインエディタではなく自分の好きなエディタを選ぶことが可能になります。
ローカル環境に色々と入れるのが面倒なので docker で簡単に構築できる環境を作成しました。先に環境だけ欲しいという方はこちらを使用してください。
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.ymlDocker環境構築
Dockerを入れてない方はこちら → Docker
./docker/DockerfileFROM 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.ymlversion: "3" services: zenn: build: context: . dockerfile: docker/Dockerfile ports: - "8000:8000" volumes: - ".:/workspace" command: npx zenn preview使い方
起動
docker-compose up記事の作成
docker exec -it zenn-env_zenn_1 zenn new:article記事の中身
./articles/{slug}.md
--- 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最後に
完成画面はこちらのような感じになります。
でけた pic.twitter.com/PC0vh7MTsO
— こぴぺたん@お刺身?×タンポポ?コンサルタント (@c_a_p_engineer) September 24, 2020Githubで管理・連携できる事からZennを使用してみようかと思います。
参考
- 投稿日:2020-09-27T11:05:13+09:00
【技術書まとめ】『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
- 投稿日:2020-09-27T10:54:17+09:00
[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.yml
とwp-content
フォルダがあれば動きます。
wp-content
の中身はdocker-compose up
すれば自動的に初期のものが構成されます。
wp-config.php
はWordPressには必須ファイルです。インストール時に自動生成してくれる?みたいなのですが、私の場合してくれなかったので公式wp-config.phpを参考に変更しました。docker-compose.ymlversion: "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.phpdefine('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の奥深いところを理解できたのではないか、そう思いました。
普段から触っている方には普通の内容だったかと思います。。。
- 投稿日:2020-09-27T10:54:17+09:00
[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.yml
とwp-content
フォルダがあれば動きます。
wp-content
の中身はdocker-compose up
すれば自動的に初期のものが構成されます。
wp-config.php
はWordPressには必須ファイルです。インストール時に自動生成してくれる?みたいなのですが、私の場合してくれなかったので公式wp-config.phpを参考に変更しました。docker-compose.ymlversion: "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.phpdefine('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の奥深いところを理解できたのではないか、そう思いました。
普段から触っている方には普通の内容だったかと思います。。。
- 投稿日:2020-09-27T03:17:49+09:00
【PHP】TCPDF + FPDIでPDFを出力してみた話
はじめに
タイトルの通りですが
TCPDFとFPDIのライブラリを使用して、PDFを出力してみました。
今回はコマンドラインから実行してみます。本編
環境構築
お好みでPHP、Composerが使用できる環境を用意してください。
Docker
今回私が使用したDocker環境は以下です(一部割愛)。
./docker-compose.ymlversion: '3' services: php: build: ./php volumes: - ./work:/home/work./php/dockerfileFROM 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.inidate.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テンプレートファイルです。
ソース
/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
実行結果
以下のようにファイルが出力された。
テンプレートなし テンプレートあり 終わりに
PDFのテンプレートの上に文字を出力できるので、フォーマットを変えずに必要な情報だけを出力できますね。
勤務表や請求書・領収書など、特定の部分だけが変動するファイルに活用できそう。
- 投稿日:2020-09-27T03:17:49+09:00
PHPのTCPDF + FPDIでPDFを出力してみた話
はじめに
タイトルの通りですが
TCPDFとFPDIのライブラリを使用して、PDFを出力してみました。
今回はコマンドラインから実行してみます。本編
環境構築
お好みでPHP、Composerが使用できる環境を用意してください。
Docker
今回私が使用したDocker環境は以下です(一部割愛)。
./docker-compose.ymlversion: '3' services: php: build: ./php volumes: - ./work:/home/work./php/dockerfileFROM 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.inidate.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テンプレートファイルです。
ソース
/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
実行結果
以下のようにファイルが出力された。
テンプレートなし テンプレートあり 終わりに
PDFのテンプレートの上に文字を出力できるので、フォーマットを変えずに必要な情報だけを出力できますね。
勤務表や請求書・領収書など、特定の部分だけが変動するファイルに活用できそう。
- 投稿日:2020-09-27T00:20:33+09:00
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.pyFlaskの内容の説明はしませんが、app.pyに
app.run()
とか@app.route('/')
とか書いてあります。これをpython app.py
するとFlaskのサイトが立ち上がります。手順2:VSCodeで開き、Docker-Containersを準備
- トップの
/simple_flask
フォルダをVSCodeで開く- 左のツールバーの機能拡張で、「remote-containers」を検索
- インストール
手順3:Docker環境を作る
- VSCodeの左下の><みたいな緑のところをクリック
画面上に出てきたものから、「Remote-Containers: Open Folder in Container...」を選択
「simple_flask」のフォルダを選択してOpen
また出てくるのでOK(これが最後)
ちなみにここでチェックオフにして、0個選択済み になっても、なんかインストールされることになるのであとの手順で確認します。
ここまでできると、下記のような画面になります。
ポイントは、右下のターミナルのところで、linuxっぽい画面になってます。(ほんとうにそうなんだけど)
ここはもう、Dockerコンテナに入ってbashを起動した状態になってます。
なのでそこで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_appPythonも入ってます。
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で普通に開いて確認、編集ができます。これを次の手順で使います。
手順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を使って、もう一度コンテナを作り直します。
これですべて完了!お疲れさまでした。
動作確認
右下のターミナルから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)以上ですー