- 投稿日:2020-06-04T17:37:26+09:00
mutagenのsyncとdocker-composeを連携させて使う
はじめに
最近Docker for MacのMutagen-based cachingを使うという記事が話題になっていたが、mutagen単体でDockerコンテナと連携するやり方が英語の記事を含めてもなかなか見つけられなかったのでまとめておく。
なお、本記事の方法ではMutagen-based cachengは利用しないため、Dockerはstable版のままでよい(上記記事の設定は試していないため動作の違い等は不明)。
またここで扱っているのはmutagenの
sync
でforward
についてはこちらの記事に載っている。環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G5033 $ docker -v Docker version 19.03.8, build afacb8b $ docker-compose -v docker-compose version 1.25.5, build 8a1c60f6準備
1. インストール
公式に書いてある通り。投稿時のバージョンは0.11.4。
$ brew install mutagen-io/mutagen/mutagen $ mutagen version 0.11.42. デーモン起動
$ mutagen daemon start
3. コンテナ起動
テスト用に用意したdocker-compose.ymlは以下。
docker-compose.ymlversion: '3.7' services: web: image: php:7.4-apache container_name: web ports: - 80:80 db: image: mysql:8.0 container_name: db environment: MYSQL_ROOT_PASSWORD: root$ docker-compose up -d手動で使う
1. セッションの作成
$ mutagen sync create --name=mutagen-test --default-file-mode-beta=644 . docker://web/var/www/htmlこちらのコマンドで
mutagen-test
という名前でカレントディレクトリ(alpha)の内容をwebコンテナの/var/www/html(beta)と同期するセッションを作成できる。なぜsource
とdest
ではなくalpha
とbeta
なのかと疑問だったが、mutagenは双方向に同期できるためのようだ。
--default-file-mode-beta=644
はbeta(コンテナ)側のファイルパーミッションを644
にする設定。mutagenのデフォルトではパーミッションがディレクトリ700
、ファイル600
になる(参考)ので、ここで指定して(もしくは--default-owner-beta=www-data
として)おかないと、今回のようにapacheから参照したい場合にパーミッションエラーになる。セッションを作成した時点で同期が始まる。これまで使っていてファイルが消えたりしたことはないが、万が一に備えてバージョン管理されている状態で行った方がよい。
2. 同期の状況の確認
- 実行時点
$ mutagen sync list -------------------------------------------------------------------------------- Name: mutage-test Identifier: sync_pPfc22rlD8RcEDldZ9CbMTJzTnRszZHfokhkZtopw7a Alpha: URL: /tmp/mutagen Connection state: Connected Beta: URL: docker://web/var/www/html DOCKER_HOST= DOCKER_TLS_VERIFY= DOCKER_CERT_PATH= Connection state: Connected Status: Watching for changes
- リアルタイム
$ mutagen sync monitor Name: mutagen-test Identifier: sync_pPfc22rlD8RcEDldZ9CbMTJzTnRszZHfokhkZtopw7a Labels: None Alpha: /tmp/mutagen Beta: docker://web/var/www/html DOCKER_HOST= DOCKER_TLS_VERIFY= DOCKER_CERT_PATH= Status: Watching for changesセッション作成直後の最初の同期中にmonitorを見ていると
Status: Staging files on beta: 41% (9191/22567)
などといった状態になり、これがStatus: Watching for changes
になったら同期完了。
ファイルの量やマシンスペックにもよると思われるが、上記の22567ファイルの規模(今回のものとは別のプロジェクト)で20秒程度だった。monitorは同期が完了しても勝手には終わらないので^Cで抜ける。3. 動作確認
- 新規作成
$ ls docker-compose.yml $ echo '<?php echo "It works!";' > index.php $ docker-compose exec web ls -la total 20 drwxrwxrwx 1 www-data www-data 4096 Jun 4 05:29 . drwxr-xr-x 1 root root 4096 May 15 12:41 .. -rw-r--r-- 1 root root 206 Jun 4 05:28 docker-compose.yml -rw-r--r-- 1 root root 24 Jun 4 05:29 index.php $ curl localhost It works!
- 編集
$ echo '<?php echo "It works fine!";' > index.php $ curl localhost It works fine!ちゃんと同期されているようだ。
今回はサイズも小さいので一瞬だが、実プロジェクトでは数秒のラグはある(コンテナでファイル自動生成などをしてすぐにホストで
git status
で見るとまだ反映されていなかったりする)。4. セッションの終了
$ mutagen sync terminate mutagen-test $ mutagen sync list Error: no matching sessions exist5. 手動の問題点
最初はこれでしばらく使っていたが、例えばセッション実行中にコンテナを落とすと、
Status: [Errored] Connecting to beta
となり同期エラーになったり、そこからdocker-compose up -d
で再度コンテナを起動しても、Status: Halted due to one-sided root emptying
となって同期はできずセッションを作り直さなければならないという問題があった。先述のオーナーやパーミッションは設定ファイルに書くこともできるが、コンテナとの連携も合わせて一括管理したいなあと思っていたところ、次の
mutagen project
を使う方法を見つけた。mutagen projectを使う
mutagenにはprojectという機能があり、セッションの作成や終了といったライフサイクルと任意のコマンドを組み合わせて設定ファイルで管理し実行できる。
公式のexamplesがわかりやすい。
今回は簡略化した以下のmutagen.ymlを使用する。
mutagen.ymlbeforeCreate: - docker-compose up -d afterTerminate: - docker-compose down sync: defaults: ignore: vcs: true mutage-test: alpha: "." beta: "docker://web/var/www/html" mode: "two-way-resolved" configurationAlpha: permissions: defaultFileMode: 644 defaultDirectoryMode: 755 configurationBeta: permissions: defaultOwner: www-data defaultGroup: www-data defaultFileMode: 644 defaultDirectoryMode: 755
beforeCreate
でセッション作成前にコンテナを起動、afterTerminate
でセッション終了後にコンテナも終了する。また、
sync
の項目にセッションの設定を書いておける。
ここではalphaのパーミッションも設定しているが、これはフレームワークなどのファイル自動生成やcomposerやnpmでのライブラリのインストールをコンテナ上で行った場合に700
や600
でホストに同期されるのを防ぐためである。公式では
afterCreate
で同期完了までのwaitを入れている。同期が速いといっても多少のラグはあるので、実プロジェクトで採用する際は真似しておくと、同期完了前にアクセスしてファイルが見つからないなどのエラーを避けられる。
docker-compose.yml
と同階層に置いてバージョン管理しておく。1. セッションの開始
$ mutagen project start Started Mutagen daemon in background (terminate with "mutagen daemon stop") > docker-compose up -d Creating network "mutagen_default" with the default driver Creating web ... done Creating db ... done Created session sync_3bwd2dlhwaFrNNeUNRe4WYegNxOdPjEj3swQ8Xx1Hz6セッション開始前にコンテナが起動しているのが確認できる。デーモンが起動していなかった場合はそっちも起動してくれて便利。
セッション実行中は
mutagen.yml.lock
というファイルができるので.gitignore
に追加しておくとよい。2. セッションの終了
$ mutagen project terminate > docker-compose down Stopping web ... done Stopping db ... done Removing web ... done Removing db ... done Removing network mutagen_default3. コマンドの実行
また、composerやnpmなどのscriptsと同様に任意のコマンドを定義できるようになっている。以下を設定ファイルに追加する。
mutagen.ymlcommands: repl: docker-compose exec web php -a db: docker-compose exec db mysql -uroot -p$ mutagen project start # セッションを終了していない場合は不要 $ mutagen project run repl Interactive shell php > echo 'hello'; hello php > ^D $ mutagen project run db Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.20 MySQL Community Server - GPL Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>おわりに
mutagen project
を利用することで、mutagenとdocker-composeを連携できて便利だった。
現状そこまで不満もないのでDockerのMutagen-based cachingがstableになるまではこの方法を使おうと思う。参考
- DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる ( こちらの記事でmutagenなるものを知りました。ありがとうございます。)
- 公式ドキュメント
- Improving performance for Docker on Mac computers when using named volumes
- Speeding Up Docker Development on the Mac
- 投稿日:2020-06-04T14:38:27+09:00
Kubernetes 構築手順 Proxy編 ※大体コピペでOK
Kubernetes 環境構築 Proxy編
Kubernetes(以下、K8s)をイントラネット内で構築する手順です。
K8s環境構築の流れを理解しつつ、作業はなるべくコピペで可能なように記載しています。1. モチベーション
- K8sを会社内の開発イントラネット内環境で構築したい。 (プロキシサーバ経由で開発イントラネット内環境からインターネットにアクセスできる場合)
- K8sを使ってみたいが、構築のハードルが高い。
2. 手順
本手順で以下のK8sクラスタ構成を構築します。
- 準備するもの
- OS : Centos7.4(minimal)
- PC 3台 ※仮想でも可
- CPU 2Core 以上
- Memroy 2GB 以上
- 出来上がるもの
- K8s クラスタ構成 ※Masterはシングル
- Master
- Worker
- Worker
2.1. Docker環境の構築(全ノード対象)
K8sは複数ノードにまたがりコンテナの駆動を管理するツールで、実際のコンテナの実行はDockerを経由しています。
また、K8sの機能もコンテナとして動作しているため、クラスタの全ノードでDockerが動作することが必要です。すでにDockerが使えている場合は先に進んでもらって結構です。
ただし、※公式推奨と ※後述の作業に必要 の作業は確認しておいてください。2.1.1. CentOS7のインストール(CLI)と基本設定
- CentOSをインストールします。
- 開発イントラネット内通信が可能となる設定をし、ローカルネットワークに接続可能な状態にしておきます。 IP,サブネットマスクの固定/MACアドレス登録など
- swapを無効化します。 ※公式推奨
- SELINUX無効化してOS再起動します。
- yumのプロキシ設定 vi /etc/yum.conf で以下のように編集→保存
#swapを無効化 swapoff -a sed -i -e "/swap/d" /etc/fstab cat /etc/fstab #SELINUX無効化してOS再起動 sed -i -e "s/^SELINUX=enforcing$/SELINUX=disabled/g" /etc/selinux/config reboot#yumのプロキシ設定 cat <<EOF >> /etc/yum.conf proxy=http://{プロキシIP}:{プロキシポート} EOF2.1.2. Dockerのインストールと設定
- Dockerインストールします。 最後にバージョンが表示されれば成功です。
- Dockerのネットワーク設定1 ※後述の作業に必要 とhello-worldコンテナの実行をします。
- うまく行かない場合は、プロキシ設定を確認します。
#Dockerインストール yum install -y yum-utils device-mapper-persistent-data lvm2 #Docker ceに必要なパッケージ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo #Docker ceのリポジトリ追加 yum install -y --setopt=obsoletes=0 docker-ce-18.06.1.ce #Docker ceインストール docker version #Dockerバージョン確認↓Dockerバージョン確認結果
Client: Version: 18.06.1-ce API version: 1.38 Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:23:03 2018 OS/Arch: linux/amd64 Experimental: false Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [root@K8sWorker1 ~]# docker version #Dockerバージョン確認 Client: Version: 18.06.1-ce API version: 1.38 Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:23:03 2018 OS/Arch: linux/amd64 Experimental: false Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?#Dockerのネットワーク設定 systemctl disable firewalld #Firewall無効化 systemctl stop firewalld #Firewall停止 mkdir -p /etc/systemd/system/docker.service.d # dockerのプロキシ設定 cat <<EOF > /etc/systemd/system/docker.service.d/http-proxy.conf #Proxy設定 [Service] Environment="HTTP_PROXY=http://{プロキシIP}:{プロキシポート}" "HTTPS_PROXY=http://{プロキシIP}:{プロキシポート}" "NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,{master nodeのIPアドレス},{worker node1のIPアドレス},{worker node2のIPアドレス}" EOF systemctl daemon-reload #プロキシ反映 systemctl enable docker && systemctl start docker #Docker再起動 docker run --rm hello-world #hello-worldコンテナ起動↓ hello-worldコンテナ起動結果
Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/# プロキシ設定を確認 docker info | grep Proxy
2.2. kubeadmインストール~kubelet有効化 (全ノード対象)
2.2.1. kubeadmインストール
#kubeadmのためのプロキシを設定してOS再起動 cat <<EOF >> ~/.bash_profile PROXY_PORT={プロキシポート} PROXY_HOST={プロキシIP} http_proxy=http://\$PROXY_HOST:\$PROXY_PORT HTTP_PROXY=\$http_proxy https_proxy=\$http_proxy HTTPS_PROXY=\$http_proxy no_proxy="localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,{master nodeのIPアドレス},{worker node1のIPアドレス},{worker node2のIPアドレス}" EOF reboot#k8sのためのyumリポジトリを追加 cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 sslverify=0 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF #kubeadmと関連パッケージのインストール yum install -y kubelet-1.16.0-0.x86_64 kubeadm-1.16.0-0.x86_64 kubectl-1.16.0-0.x86_64 --disableexcludes=kubernetes2.2.2. kubelet有効化
- リソース管理ドライバをcgroupfsに統一します。 ※Docker daemonの設定(デフォルトではsystemd)をkubelet側(cgroupfs)に合わせる。
- kubelet有効化と確認をします。※起動してなくてOK
- ブリッジの設定をします。
#リソース管理ドライバをcgroupfsに統一 cat << EOF > /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=cgroupfs"] } EOF systemctl restart docker docker info | grep -i cgroup# kubelet有効化と確認 systemctl enable kubelet && systemctl start kubelet systemctl status kubelet↓ kubelet確認
● kubelet.service - kubelet: The Kubernetes Node Agent Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled) Drop-In: /usr/lib/systemd/system/kubelet.service.d mq10-kubeadm.conf Active: activating (auto-restart) (Result: exit-code) since Tue 2020-06-02 17:00:13 JST; 932ms ago Docs: https://kubernetes.io/docs/ Process: 16490 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=255) Main PID: 16490 (code=exited, status=255) Jun 02 17:00:13 K8sWorker2.localdomain systemd[1]: Unit kubelet.service enter... Jun 02 17:00:13 K8sWorker2.localdomain systemd[1]: kubelet.service failed. Hint: Some lines were ellipsized, use -l to show in full.#ブリッジの設定 cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system
2.3. K8sクラスタ構築
2.3.1. Masterの構築 (Masterノード対象)
この作業はMasterノードでのみ行います。
- /tmpに以下のファイルを配置しておきます。 > https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml > kube-flannel-ds-amd64がPullできない場合があります。 > kube-flannel.ymlを編集し、今回はイメージのロード先を easzlabに変更しました。 ※2020/06/02 時点
- kubeadmを実行します。 tokenが出力されるので控えておきます。
- 設定の編集をします。 最後にcreatedが10個表示されればOK
- Podを確認します。 Podが8個あり、すべてRunningになっていればOK
# イメージのロード先変更 ※他箇所あり initContainers: - name: install-cni image: easzlab/flannel:v0.12.0-amd64 command:#kubeadmを実行 kubeadm init --kubernetes-version 1.16.0 --apiserver-advertise-address={master nodeのIPアドレス} --pod-network-cidr=10.244.0.0/16 --token-ttl 0 --image-repository gotok8s↓kubeadmを実行結果
To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join {master nodeのip}:6443 --token oe4by1.8wxrpf52w2y6xulw \ --discovery-token-ca-cert-hash sha256:a184db6aaaa3529ea9cb4f46038945ceae4878e16f21213aac1a605583071d19# 設定の編集 mkdir -p $HOME/.kube #これをやらないと動作しない場合あり。 sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config #これをやらないと動作しない場合あり。 sudo chown $(id -u):$(id -g) $HOME/.kube/config #これをやらないと動作しない場合あり。 kubectl apply -f /tmp/kube-flannel.yml #kube-flannel設定反映#Podを確認 kubectl get pods --all-namespaces↓Pod確認結果
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-8655596978-ff4rv 1/1 Running 0 69s kube-system coredns-8655596978-tprdp 1/1 Running 0 69s kube-system etcd-k8smaster1.localdomain 1/1 Running 0 27s kube-system kube-apiserver-k8smaster1.localdomain 1/1 Running 0 19s kube-system kube-controller-manager-k8smaster1.localdomain 1/1 Running 0 12s kube-system kube-flannel-ds-amd64-7vjkq 1/1 Running 0 37s kube-system kube-proxy-4562b 1/1 Running 0 69s kube-system kube-scheduler-k8smaster1.localdomain 1/1 Running 0 9s
2.3.2. Workerの構築 (Workerノード対象)
この作業はWorkderノードでのみ行います。
- Masterから設定のコピーをします。
- クラスターに参加します。
#Masterから設定のコピー mkdir -p /etc/cni/net.d/ scp {master nodeのIPアドレス}:/etc/cni/net.d/10-flannel.conflist /etc/cni/net.d/10-flannel.conflist #クラスターに参加 kubeadm join {master nodeのIPアドレス}:6443 --token {上述の作業で控えた値} \ --discovery-token-ca-cert-hash sha256:{上述の作業で控えた値}2.3.3. ノードの確認
- それぞれのノードがクラスタに参加していることを確認します。
#ノードの確認 kubectl get nodes
↓ ノードの確認結果
NAME STATUS ROLES AGE VERSION k8smaster1.localdomain Ready master 17h v1.16.0 k8sworker1.localdomain Ready <none> 2m26s v1.16.0 k8sworker2.localdomain Ready <none> 82s v1.16.0
3. 動作確認
3.1. ダッシュボードの表示
- 外部からアクセスできるようにrecommended.yamlを編集し、Masterノードの/tmpに配置しておきます。 https://github.com/kubernetes/dashboard
- ダッシュボードのPodを作成します。
- admin-userを作成し、トークンを作ります。
- 以下URLにアクセスし、トークンを入力するとダッシュボードが開きます。 https://{master nodeのIP}:30843
--- # 外部からアクセスできるようにrecommended.yaml編集 kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: type: NodePort #追加 ports: - port: 443 targetPort: 8443 nodePort: 30843 #追加 selector: k8s-app: kubernetes-dashboard ---#ダッシュボードのPodを作成 kubectl apply -f /tmp/recommended.yaml kubectl get pod --namespace=kubernetes-dashboard# admin-userを作る cat <<EOF > service-account.yaml apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kube-system EOF kubectl apply -f service-account.yaml #ユーザをデプロイ kubectl -n kube-system get secret | grep admin #権限を表示#トークン取得 kubectl -n kube-system describe secret admin-user-token-n72ds3.2. コンテナ起動
コンテナを起動してみます。
3.2.1. Podのデプロイ
まずは、K8sではマニフェストファイル(YAML)を作成し、それをkubectl applyすることでコンテナをPodという単位で起動(デプロイ)します。
ここで気がつくのが、構築の時点でkubectl applyを使っていたということです。
つまり、K8sクラスターはポッドとサービスにより提供されているということです。この段階では、クラスタノードからはコンテナにアクセスできるが外部からはアクセスできません。
3.2.2. サービスのデプロイ
外部からアクセスを可能にするために、サービスを追加しノードのポートとPodのポートを接続します。3.2.1. Podのデプロイ
- Podをデプロイします。
- PodのIPを確認します。
- 確認したIPに対してアクセスしてみます。
Welcome to nginx!のHTML
が表示されます。- ブラウザで
http://{PodのIP}:80
にアクセスしてみます。不能となります。# Podをデプロイ cd /tmp cat <<EOF > deployments.yml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 EOF kubectl apply -f deployments.yml#PodのIPを確認 kubectl get pod -o wide3.2.2. サービスのデプロイ
- サービスをデプロイします。
http://10.10.33.72:30036/
にアクセスします。Welcome to nginx!
のページが表示されます。# サービスをデプロイ cat <<EOF > service.yml kind: Service apiVersion: v1 metadata: name: my-service spec: type: NodePort ports: - name: http port: 80 targetPort: 80 nodePort: 30036 protocol: TCP selector: # 1Pod複数コンテナの場合は、ココでパケットを振り分ける。 app: nginx EOF kubectl apply -f service.yml4. まとめ
上述の手順で以下が達成できました。
- イントラネット環境内でK8sクラスターの構築
- 任意コンテナデプロイ
4.1. おさらい
- K8sはコンテナエンジンの上位レイヤのサービスであり、コンテナエンジンが駆動していることは前提条件(今回はDocker)
- K8sを駆動させるのに必要なものは以下
- 任意のコンテナはPodとサービスを使ってデプロイする。
4.2. 次のステップ
- ヘルスチェック・冗長性設定
- Master 兼 Worker設定
- イントラネット内コンテナレジストリ・レポジトリとの連携
- 投稿日:2020-06-04T14:11:54+09:00
【dcoker, gitlab-ci】 ERROR: unsatisfiable constraints の対応
問題
gitlab-ci上でこれまで正常に動いていた処理にて、
ERROR: unsatisfiable constraints
が発生
alpineイメージ絡みの問題らしい。エラー内容
$ apk add --no-cache curl jq python3 py3-pip fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz ERROR: unsatisfiable constraints: python (missing): required by: world[python]対応方法
- pythonをバージョン2から3ににする
$ apk add --no-cache curl jq python py-pip参考
github
https://github.com/docker-library/docker/commit/eb305f7
alpineリリースノート
https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.12.0#python2_no_longer_provides_python_and_python-devel
- 投稿日:2020-06-04T13:19:06+09:00
Docker初心者がDockerfileを使ってalpineのDockerイメージをビルドする
Dockerfile
qiita DockerfileFROM alpine:3.12.0 LABEL version="1.0" LABEL description="Dockerfile test at alpine"前提
docker for mac を起動しておくこと
ディレクトリ
DockerFileTest
>Dockerfileコマンド
mac:terminal
qiita terminalcd DockerfileTest docker build .
※build . でDockerfileTestディレクトリ内からDockerfileを探し、その中で定義されているイメージをビルドします。
コンテナ生成は行われません。
- 投稿日:2020-06-04T09:32:40+09:00
laravel nginxでroot以外のページがNot Foundになってしまうとき、これをconfに書く。
dockerでngixを追加してやってみたときの話。
rootのいつものLaravelの画面は出るが、追加したURLでNot Foundになってしまう。404 Not Found
nginx/1.19.0解決策
try_files $uri $uri/ /index.php?$query_string;
を書くnginx/default.confserver { listen 80; index index.php index.html; root /var/www/public; location / { root /var/www/public; index index.html index.php; try_files $uri $uri/ /index.php?$query_string; # <== }nginxのconfにこれがないと/以外のときNot foundになる。
dockerでnginxでやろうと思ってやるとはまる。
"Docker Laravel"で検索したページでもここを強調して書かれているところはないと思うので書きました。公式に書いてました。
参考
Installation - Laravel - The PHP Framework For Web Artisans
- 投稿日:2020-06-04T09:11:21+09:00
dockerfileで親ディレクトリを参照したい!
はじめに
会社の研修で詰まったところをメモ程度に書いていく
やりたかったこと
以下のようなディレクトリ構造の時、dokerfileから親ディレクトリのindex.htmlをCOPYしたかった
ディレクトリ構造content/ │ ├ .infrastructure/ │ ∟ dockerfile │ ├ files/ ∟ index.htmldockerfileFROM: nginx:latest COPY: ../files/ /usr/share/nginx/html WORKDIR /usr/share/nginx/htmlこれで.infrastructureディレクトリで
docker build
を実行。実行結果
.infrastructure $ docker build . -t docker-html -- 実行結果 -- Sending build context to Docker daemon 3.072kB Step 1/2 : FROM nginx:latest ---> 9beeba249f3e Step 2/2 : COPY ../files/ /usr/share/nginx/html COPY failed: Forbidden path outside the build context: ../files/ ()このように
COPY failed: Forbidden path outside the build context: ../files/ ()
と表示され親ディレクトリを参照できない解決方法
-f オプションを使って、
content
ディレクトリからdocker build
コマンドを実行する
以下の通り# docker build -f [dockerfileの指定] -t [イメージ名] [イメージを作成する時に参照するディレクトリ] $ docker build -f .infrastructure/dockerfile -t image_name .注意点
最後の
.
忘れないように!
今回の場合はカレントディレクトリからimageを作成するため.
。まとめ
dockerfileから別のディレクトリのファイルを参照することはできない。
なので、親ディレクトリから-fオプションを用いてコマンドを実行すれば良い。
- 投稿日:2020-06-04T08:39:55+09:00
Redmine on Docker
はじめに
本記事は動画( https://youtu.be/-DrdYw8fHwc )で説明に使用している
スライドを記事化したものです。動画と合わせて御覧ください。
※記事化する際に補足説明を加筆しており、内容は動画のスライドと異なります。
※本記事の内容は2020年3月時点の内容となります。OSやミドルウェア、Dockerのバージョンが異なることで記載通りの内容で完了しない場合があります。
ミドルウェア構成
- OS : CentOS 7.8
- Webサービス : Apache 2.4.6
- アプリ言語 : Ruby 2.4
- DBサービス : MariaDB 10.4.3
- Redmine : Redmine 4.1
Dockerfileで下準備
# centos7のイメージを利用する FROM centos:7 LABEL maintainer=Takemi SHELL ["/bin/bash", "-o", "pipefail", "-c"]" # 累積アップデートの実行 RUN yum -y upgrade #takemiユーザが存在していない場合ユーザ追加する RUN echo 'make user takemi' RUN adduser -m takemi;echo "takemi:takemi123" | chpasswd; #sshのインストール RUN yum install -y openssh-server RUN systemctl enable sshd #Apacheのインストール RUN yum install -y httpd RUN systemctl enable httpd #MariaDBのインストール RUN curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash RUN yum install -y MariaDB-server MariaDB-devel MariaDB-shared RUN systemctl enable mariadb #ruby インストール準備 RUN yum -y groupinstall "Development Tools" RUN yum -y install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel libffi-devel RUN yum -y install httpd-devel RUN yum -y install ImageMagick ImageMagick-devel ipa-pgothic-fonts WORKDIR /root RUN curl -O https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.1.tar.gz RUN tar xf ruby-2.4.1.tar.gz WORKDIR /root/ruby-2.4.1 RUN ./configure --disable-install-doc RUN make RUN make install RUN gem install bundler --no-rdoc --no-ri> docker build -t redmine .Dockerfileでやってること!
- OSのイメージ構築
- OSのアップデート
- ルートユーザパスワード発行
- 一般ユーザ作成、パスワード発行
- sshのインストール
- Apacheのインストール
- MariaDBのインストール
- Rubyのインストール
DBの設定
DBのrootユーザの追加
root > mysql mysql > GRANT ALL PRIVILEGES ON *.* TO 'takemi'@'localhost' IDENTIFIED BY 'takemi123' WITH GRANT OPTION; mysql > FLUSH PRIVILEGES;※DBのユーザ名とOSのユーザ名を合わせておくと、OSのログインユーザがmysqlコマンドを実行する時にユーザ名指定を省略することができるようになります。
Redmineのインストール
root > cd /var/www root > svn co https://svn.redmine.org/redmine/branches/4.1-stable redmine-4.1 user > cd redmin-4.1 user > cd config user > cp configuration.yml.example configuration.yml user > cp database.yml.example database.yml user > vi database.yml username: takemi password: "takemi123" root > cd /var/www root > chown -R takemi:takemi redmine-4.1 root > vi /etc/group takemi:x:1000:apache root > cd /var/www/redmine-4.1 root > gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/' root > bundle install --without development test --path vendor/bundle root > bundle exec rake generate_secret_token root > gem install passenger --no-rdoc --no-ri root > passenger-install-apache2-module --auto root > passenger-install-apache2-module --snippet root > vi /etc/httpd/conf.d/redmine.conf root > systemctl restart httpd user > mysql -p create database redmine default character set utf8; user > RAILS_ENV=production bundle exec rake db:migrate user > RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_dataRedmineのセットアップ
ブラウザでアクセス!
詳しくは動画で!
- 投稿日:2020-06-04T00:52:29+09:00
Dockerfile for Rails6のベストプラクティスを解説
本記事の趣旨
令和時代のRails運用
こちらのスライドに掲載されている以下のDockerfileが、キャッシュやマルチステージビルドを利用したベストプラクティスとして参考になりました。Dockerfile# syntax = docker/dockerfile:experimental # Node.jsダウンロード用ビルドステージ FROM ruby:2.6.5 AS nodejs WORKDIR /tmp # Node.jsのダウンロード RUN curl -LO https://nodejs.org/dist/v12.18.0/node-v12.18.0-linux-x64.tar.xz RUN tar xvf node-v12.18.0-linux-x64.tar.xz RUN mv node-v12.18.0-linux-x64 node FROM ruby:2.6.5 # nodejsをインストールしたイメージからnode.jsをコピーする COPY --from=nodejs /tmp/node /opt/node ENV PATH /opt/node/bin:$PATH # アプリケーション起動用のユーザーを追加 RUN useradd -m -u 1000 rails RUN mkdir /app && chown rails /app USER rails # yarnのインストール RUN curl -o- -L https://yarnpkg.com/install.sh | bash ENV PATH /home/rails/.yarn/bin:/home/rails/.config/yarn/global/node_modules/.bin:$PATH # ruby-2.7.0でnewした場合を考慮 RUN gem install bundler WORKDIR /app # Dockerのビルドステップキャッシュを利用するため # 先にGemfileを転送し、bundle installする COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/ RUN bundle config set app_config .bundle RUN bundle config set path .cache/bundle # mount cacheを利用する RUN --mount=type=cache,uid=1000,target=/app/.cache/bundle \ bundle install && \ mkdir -p vendor && \ cp -ar .cache/bundle vendor/bundle RUN bundle config set path vendor/bundle RUN --mount=type=cache,uid=1000,target=/app/.cache/node_modules \ bin/yarn install --modules-folder .cache/node_modules && \ cp -ar .cache/node_modules node_modules COPY --chown=rails . /app RUN --mount=type=cache,uid=1000,target=/app/tmp/cache bin/rails assets:precompile # 実行時にコマンド指定が無い場合に実行されるコマンド CMD ["bin/rails", "s", "-b", "0.0.0.0"]ここで使用されているBuildkitなどの要素について、勉強した内容をまとめたいと思います。
これらの方法により、開発効率の向上を実感しましたので、RailsとDockerを学習中の方のご参考になればと思います。
(投稿者はDockerを勉強中で、実務は未経験ですので、気になる点がありましたらコメントでご指摘をお願いします。)
注記:上記のDockerfileは、元スライドの物から、Node.jsのバージョンだけ、20/6/6時点での最新verに変更しています。
参考記事
Dockerfileを改善するためのBest Practice 2019年版
Docker Buildにおけるリードタイム短縮のための3つの改善ポイント
開発環境
- Mac OS X 10.15.4
- Docker 19.03.8
- Docker Desktop for Mac 2.3.0.3
- Ruby 2.6.5 Rails 6.0.2
Dockerfileの解説
上記のDockerfileの要点を見ていきます。
1行目の# syntax =
という部分は後述するBuildkitに関する記述です。その次の
# Node.jsダウンロード用ビルドステージ FROM ruby:2.6.5 AS nodejs WORKDIR /tmp # Node.jsのダウンロード RUN curl -LO https://nodejs.org/dist/v12.18.0/node-v12.18.0-linux-x64.tar.xz RUN tar xvf node-v12.18.0-linux-x64.tar.xz RUN mv node-v12.18.0-linux-x64 nodeここでは、Railsに必要なNode.jsをインストールしています。
- tmpに移動
- node-v12.18.0-linux-x64.tar.xzをダウンロード、展開
- node-v12.18.0-linux-x64をnodeにリネーム
の結果、
/tmp/node
(本体),/tmp/node-v12.18.0-linux-x64.tar.xz
(不要)
が生成されます。最終的なDockerイメージを軽量にするために、必要なnode本体だけを残す必要があります。Dockerはレイヤー構造で履歴が残っているため、ただ単に
RUN rm node-v12.18.0-linux-x64.tar.xz
としても意味がないようです。そこで、マルチステージビルドを利用しています。
マルチステージビルド
マルチステージビルドは、1つのDockerfileに複数のステージを分けて記述し、最後のステージの内容だけが最終イメージに含まれます。
例のDockerfileでは、FROM
行が2箇所、つまり2つのステージがあります。FROM ruby:2.6.5 AS nodejs ... FROM ruby:2.6.51つ目の
AS nodejs
の記載で、ステージにnodejs
と名付けています。これによって、2つ目のステージで、# nodejsをインストールしたイメージからnode.jsをコピーする COPY --from=nodejs /tmp/node /opt/node ENV PATH /opt/node/bin:$PATH上でインストールした
tmp/node
だけをコピーする事ができます。今回の場合は、これによって節約できるのは15MBほどですが、Goのようなコンパイル言語で、ビルド結果のファイルだけを次のステージに渡すと、かなりの軽量化ができるようです。
ちなみに、2つ目のステージのyarnインストールは、ファイルそのものではなく、install.shをダウンロードして実行しているだけで、不要なファイルが残らないため、このままで問題ないのだと思います。
# yarnのインストール RUN curl -o- -L https://yarnpkg.com/install.sh | bash ENV PATH /home/rails/.yarn/bin:/home/rails/.config/yarn/global/node_modules/.bin:$PATHユーザーの追加
# アプリケーション起動用のユーザーを追加 RUN useradd -m -u 1000 rails RUN mkdir /app && chown rails /app USER railsここでは、コンテナ内にユーザーを追加しています。デフォルトのrootユーザーのままでは、ホストとファイルを共有する際に権限の問題が発生するようです。
ただ、Docker for Macの場合、その問題は起こらないので、この設定は省略しても良いかもしれません。
(非rootユーザーにすると、vimを使いたい時にapt-getができないなど、色々と困る場面もありましたので..)bundle install
WORKDIR /app # Dockerのビルドステップキャッシュを利用するため # 先にGemfileを転送し、bundle installする COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/作業ディレクトリに必要なパッケージ管理ファイルを置いています。その後、
RUN bundle config set app_config .bundle RUN bundle config set path .cache/bundleまず
bundle config
コマンドを使用して、installするpathを設定しています。bundle config
例として、
bundle config set path vendor/bundle
と設定しておくと、bundle install
の際に、bundle install --path vendor/bundle
とパスを指定した事と同じになります。installの際に、
--path
を指定する方法は非推奨となったようなので、今後はbundle config
を使いましょう。Cache Mount
bundle install
で、ビルド効率のためにCache Mountを利用しています。RUN bundle config set path .cache/bundle # mount cacheを利用する RUN --mount=type=cache,uid=1000,target=/app/.cache/bundle \ bundle install && \ mkdir -p vendor && \ cp -ar .cache/bundle vendor/bundle RUN bundle config set path vendor/bundleまずbundleのinstall先を
.cache/bundle
に設定します。続く
--mount=type=cache
〜target=/app/.cache/bundle
という記載が、Cache Mountを利用している部分です。
この記載を含むRUN命令の中では、targetに指定したpath(ここでは/app/.cache/bundle
)の中身が、ホスト内に保存され、次回以降のbuildでcacheとして利用されるようになります。したがって、直後の
bundle install
で.cache/bundle
にインストールされたgemは、ホスト内部に保存されています。
このままだと、コンテナ内にgemがない状態になってしまうため、続けてvendorディレクトリを作り、そこに.cacheディレクトリから中身をコピーしています。最後に
bundle config set path vendor/bundle
でpathを指定することで、bundlerがvendor/bundleを読みに行ってくれるようになります。やや回りくどい気もしますが、これによってbuild時間が劇的に改善しました。こちらによると、
RUN --mount=type=cache
命令をうまく活用すると,従来のdocker build
より33倍以上速いビルドも可能です.私の環境ではbuildのたびにbundle installで300秒以上かかっていました。cacheがあれば、build時のbundle installは変更差分のみですぐ終わるので、気軽にbuildできます。
Buildkit
上述のCache Mountを使うためには、Buildkitでbuildをする必要があります。
Buildkitとは、dockerのイメージビルドを便利にしてくれるビルドツールキットです。こちらにあるように、ビルドのそれぞれの過程ごとにかかった時間を表示してくれたりします。
他にもビルドの並列実行など、たくさんの機能があるようです。Buildkitの導入
主に2つの方法があります。
- 環境変数
DOCKER_BUILDKIT=1
を設定する。- 試験機能モードを有効にすることで
docker buildx
コマンドを使う(Docker 19.03以上)。1つ目は、
DOCKER_BUILDKIT=1 docker build .
のように環境変数を指定する簡単な方法です。2つ目は、buildxというプラグインを利用する方法で、buildkitの全ての機能が有効になるとのことです。config.json (デフォルトでは
~/.docker/config.json
) に次のように指定します。~/.docker/config.json{ "experimental": "enabled" }これにより、環境変数なしで
docker buildx build .
のようにビルドを実行する事ができます。
BuildKitによりDockerとDocker Composeで外部キャッシュを使った効率的なビルドをする方法Buildkit Cache Mountの利用
--mount
は新しい構文のため、Dockerfileの1行目に次の記述をする必要があります。# syntax = docker/dockerfile:experimental
Cacheの削除
docker builder prune
以上がbuildkitの使い方です。
簡単な設定をするだけで良いので、cacheを使わない場合も、取り入れてみるといいかもしれません。yarn install
RUN --mount=type=cache,uid=1000,target=/app/.cache/node_modules \ bin/yarn install --modules-folder .cache/node_modules && \ cp -ar .cache/node_modules node_modulesyarn installも同じくCache Mountを使います。
asset precompile
COPY --chown=rails . /app RUN --mount=type=cache,uid=1000,target=/app/tmp/cache bin/rails assets:precompile最後にホストのファイルを全てコピーして、Cache Mountを利用してアセットをプリコンパイルします。
開発環境と本番環境でさらにステージを分けて、本番環境でのみプリコンパイルを行うなどの設定も考えられます。
- 投稿日:2020-06-04T00:52:29+09:00
Dockerイメージを快適にビルド for Rails6
本記事の趣旨
令和時代のRails運用
こちらのスライドに掲載されている以下のDockerfileが、キャッシュやマルチステージビルドを利用したベストプラクティスとして参考になりました。Dockerfile# syntax = docker/dockerfile:experimental # Node.jsダウンロード用ビルドステージ FROM ruby:2.6.5 AS nodejs WORKDIR /tmp # Node.jsのダウンロード RUN curl -LO https://nodejs.org/dist/v12.14.1/node-v12.14.1-linux-x64.tar.xz RUN tar xvf node-v12.14.1-linux-x64.tar.xz RUN mv node-v12.14.1-linux-x64 node FROM ruby:2.6.5 # nodejsをインストールしたイメージからnode.jsをコピーする COPY --from=nodejs /tmp/node /opt/node ENV PATH /opt/node/bin:$PATH # アプリケーション起動用のユーザーを追加 RUN useradd -m -u 1000 rails RUN mkdir /app && chown rails /app USER rails # yarnのインストール RUN curl -o- -L https://yarnpkg.com/install.sh | bash ENV PATH /home/rails/.yarn/bin:/home/rails/.config/yarn/global/node_modules/.bin:$PATH # ruby-2.7.0でnewした場合を考慮 RUN gem install bundler WORKDIR /app # Dockerのビルドステップキャッシュを利用するため # 先にGemfileを転送し、bundle installする COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/ RUN bundle config set app_config .bundle RUN bundle config set path .cache/bundle # mount cacheを利用する RUN --mount=type=cache,uid=1000,target=/app/.cache/bundle \ bundle install && \ mkdir -p vendor && \ cp -ar .cache/bundle vendor/bundle RUN bundle config set path vendor/bundle RUN --mount=type=cache,uid=1000,target=/app/.cache/node_modules \ bin/yarn install --modules-folder .cache/node_modules && \ cp -ar .cache/node_modules node_modules COPY --chown=rails . /app RUN --mount=type=cache,uid=1000,target=/app/tmp/cache bin/rails assets:precompile # 実行時にコマンド指定が無い場合に実行されるコマンド CMD ["bin/rails", "s", "-b", "0.0.0.0"]ここで使用されているBuildkitなどの要素について、勉強した内容をまとめたいと思います。
これらの方法により、開発効率の向上を実感しましたので、RailsとDockerを学習中の方のご参考になればと思います。
(投稿者はDockerを勉強中で、実務は未経験ですので、気になる点がありましたらコメントでご指摘をお願いします。)
参考記事
Dockerfileを改善するためのBest Practice 2019年版
Docker Buildにおけるリードタイム短縮のための3つの改善ポイント
開発環境
- Mac OS X 10.15.4
- Docker 19.03.8
- Docker Desktop for Mac 2.3.0.3
- Ruby 2.6.5 Rails 6.0.2
Dockerfileの解説
上記のDockerfileの要点を見ていきます。
1行目の# syntax =
という部分は後述するBuildkitに関する記述です。その次の
# Node.jsダウンロード用ビルドステージ FROM ruby:2.6.5 AS nodejs WORKDIR /tmp # Node.jsのダウンロード RUN curl -LO https://nodejs.org/dist/v12.14.1/node-v12.14.1-linux-x64.tar.xz RUN tar xvf node-v12.14.1-linux-x64.tar.xz RUN mv node-v12.14.1-linux-x64 nodeここでは、Railsに必要なNode.jsをインストールしています。
- tmpに移動
- node-v12.14.1-linux-x64.tar.xzをダウンロード、展開
- node-v12.14.1-linux-x64をnodeにリネーム
の結果、
/tmp/node
(本体),/tmp/node-v12.14.1-linux-x64.tar.xz
(不要)
が生成されます。最終的なDockerイメージを軽量にするために、必要なnode本体だけを残す必要があります。Dockerはレイヤー構造で履歴が残っているため、ただ単に
RUN rm node-v12.14.1-linux-x64.tar.xz
としても意味がないようです。そこで、マルチステージビルドを利用しています。
マルチステージビルド
マルチステージビルドは、1つのDockerfileに複数のステージを分けて記述します。
例のDockerfileでは、FROM
行が2箇所、つまり2つのステージがあります。FROM ruby:2.6.5 AS nodejs ... FROM ruby:2.6.51つ目の
AS nodejs
の記載で、ステージにnodejs
と名付けています。これによって、2つ目のステージで、# nodejsをインストールしたイメージからnode.jsをコピーする COPY --from=nodejs /tmp/node /opt/node ENV PATH /opt/node/bin:$PATH上でインストールした
tmp/node
だけをコピーする事ができます。今回の場合は、これによって節約できるのは15MBほどですが、Goのようなコンパイル言語で、ビルド結果のファイルだけを次のステージに渡すと、かなりの軽量化ができるようです。
ちなみに、2つ目のステージのyarnインストールは、ファイルそのものではなく、install.shをダウンロードして実行しているだけで、不要なファイルが残らないため、このままで問題ないのだと思います。
# yarnのインストール RUN curl -o- -L https://yarnpkg.com/install.sh | bash ENV PATH /home/rails/.yarn/bin:/home/rails/.config/yarn/global/node_modules/.bin:$PATHユーザーの追加
# アプリケーション起動用のユーザーを追加 RUN useradd -m -u 1000 rails RUN mkdir /app && chown rails /app USER railsここでは、コンテナ内にユーザーを追加しています。デフォルトのrootユーザーのままでは、ホストとファイルを共有する際に権限の問題が発生するようです。
ただ、Docker for Macの場合、その問題は起こらないので、この設定は省略しても良いかもしれません。
(非rootユーザーにすると、vimを使いたい時にapt-getができないなど、色々と困る場面もありましたので..)bundle install
WORKDIR /app # Dockerのビルドステップキャッシュを利用するため # 先にGemfileを転送し、bundle installする COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/作業ディレクトリに必要なパッケージ管理ファイルを置いています。その後、
RUN bundle config set app_config .bundle RUN bundle config set path .cache/bundleまず
bundle config
コマンドを使用して、installするpathを設定しています。bundle config
例として、
bundle config set path vendor/bundle
と設定しておくと、bundle install
の際に、bundle install --path vendor/bundle
とパスを指定した事と同じになります。installの際に、
--path
を指定する方法は非推奨となったようなので、今後はbundle config
を使いましょう。Cache Mount
RUN bundle config set path .cache/bundle # mount cacheを利用する RUN --mount=type=cache,uid=1000,target=/app/.cache/bundle \ bundle install && \ mkdir -p vendor && \ cp -ar .cache/bundle vendor/bundle RUN bundle config set path vendor/bundleまずbundleのinstall先を
.cache/bundle
に設定します。続く
--mount=type=cache
〜target=/app/.cache/bundle
という記載が、Cache Mountを利用している部分です。
この記載を含むRUN命令の中では、targetに指定したpath(ここでは/app/.cache/bundle
)の中身が、ホスト内に保存され、次回以降のbuildでcacheとして利用されるようになります。したがって、直後の
bundle install
で.cache/bundle
にインストールされたgemは、ホスト内部に保存されています。
このままだと、コンテナ内にgemがない状態になってしまうため、続けてvendorディレクトリを作り、そこに.cacheディレクトリから中身をコピーしています。最後に
bundle config set path vendor/bundle
でpathを指定することで、bundlerがvendor/bundleを読みに行ってくれるようになります。やや回りくどい気もしますが、これによってbuild時間が劇的に改善しました。こちらによると、
RUN --mount=type=cache
命令をうまく活用すると,従来のdocker build
より33倍以上速いビルドも可能です.私の環境ではbuildのたびにbundle installで300秒以上かかっていました。cacheがあれば、build時のbundle installは変更差分のみですぐ終わるので、気軽にbuildできます。
Buildkit
上述のCache Mountを使うためには、Buildkitでbuildをする必要があります。
Buildkitとは、dockerのイメージビルドを便利にしてくれるビルドツールキットです。こちらにあるように、ビルドのそれぞれの過程ごとにかかった時間を表示してくれたりします。
他にもビルドの並列実行など、たくさんの機能があるようです。Buildkitの導入
主に2つの方法があります。
- 環境変数
DOCKER_BUILDKIT=1
を設定する。- 試験機能モードを有効にすることで
docker buildx
コマンドを使う(Docker 19.03以上)。1つ目は、
DOCKER_BUILDKIT=1 docker build .
のように環境変数を指定する簡単な方法です。2つ目は、buildxというプラグインを利用する方法で、buildkitの全ての機能が有効になるとのことです。config.json (デフォルトでは
~/.docker/config.json
) に次のように指定します。~/.docker/config.json{ "experimental": "enabled" }これにより、環境変数なしで
docker buildx build .
のようにビルドを実行する事ができます。
BuildKitによりDockerとDocker Composeで外部キャッシュを使った効率的なビルドをする方法Buildkit Cache Mountの利用
--mount
は新しい構文のため、Dockerfileの1行目に次の記述をする必要があります。# syntax = docker/dockerfile:experimental
Cacheの削除
docker builder prune
以上がbuildkitの使い方です。
簡単な設定をするだけで良いので、cacheを使わない場合も、取り入れてみるといいかもしれません。yarn install
RUN --mount=type=cache,uid=1000,target=/app/.cache/node_modules \ bin/yarn install --modules-folder .cache/node_modules && \ cp -ar .cache/node_modules node_modulesyarn installも同じくCache Mountを使います。
asset precompile
COPY --chown=rails . /app RUN --mount=type=cache,uid=1000,target=/app/tmp/cache bin/rails assets:precompile最後にホストのファイルを全てコピーして、Cache Mountを利用してアセットをプリコンパイルします。
開発環境と本番環境でさらにステージを分けて、本番環境でのみプリコンパイルを行うなどの設定も考えられます。
- 投稿日:2020-06-04T00:29:20+09:00
ローカル環境でnginxをhttps通信をする方法
はじめに
就活中の選考課題でGeolocation apiを使って、位置情報を利用するサイトを作る際に
Google chromeのブラウザでは、https通信しないと位置情報を取得できないので、
https通信をできるようにしました。
この記事は、ゆうきゃんさんの記事である最強のLaravel開発環境をDockerを使って構築する【新編集版】をベースにhttps通信を構築しています。1から環境を用意したい方は、この記事はじめに参照してから記事をご覧ください。開発環境
開発環境 Windows10 Home docker tool box 19.03.1 docker-compose 1.24.1 Mysql 8.0.20 Nginx 1.18.0 https通信する手順
Chocolateyのインストール
https通信に必要なssl証明書を簡単に発行することができるmkcertツールインストールするために
Chocolateyというパッケージ管理ツールをインストールします①スタートメニューを右クリックしてコマンドプロンプトを管理者権限で開く
②コマンドか公式サイトからChocolateyインストール・コマンド C:\>Chocolatey Install Chocolatey v0.10.15C:\>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))`mkcertのインストールしてSSL証明書発行
C:\>choco install mkcert C:\>mkcert localhost 196.168.99.101(ご自身のIPアドレスを入力) mkcert localhost 196.168.99.101 Using the local CA at "C:\Users\ユーザ名\AppData\Local\mkcert" Created a new certificate valid for the following names - "localhost" - "196.168.99.101(ご自身のIPアドレス)" The certificate is at "./localhost+1.pem" and the key at "./localhost+1-key.pem"発行したら今いるディレクトリに発行させるので
localhost+1.pem localhost+1-key.pemの+1を消して
docker-laravel\infrastructure\docker\nginxのディレクトリに移動します⚠もし、mkcert localhost 196.168.99.101(ご自身のIPアドレスを入力)と打って
システムリソース不足のため...と言われたら、
セキュリティーソフトのリアルタイムスキャンの停止や再起動をして見てくださいdocker-compose.ymlの記述
web: build: ./docker/nginx ports: - 196.168.99.101:80:80 - 196.168.99.101:443:443(ここを追加で記述する) volumes: - php-fpm-socket:/var/run/php-fpm - ../backend:/work/backendDockerfileの記述
FROM node:14.2-alpine as node FROM nginx:1.18-alpine SHELL ["/bin/ash", "-oeux", "pipefail", "-c"] ENV TZ=UTC RUN apk update && \ apk add --update --no-cache --virtual=.build-dependencies g++ COPY --from=node /usr/local/bin /usr/local/bin COPY --from=node /opt /opt COPY ./default.conf /etc/nginx/conf.d/default.conf ADD ./localhost.pem /etc/certs/localhost.pem(ここを追加で記述する) ADD ./localhost-key.pem /etc/certs/localhost-key.pem(ここを追加で記述する) WORKDIR /work/backenddefault.confの記述
access_log /dev/stdout main; error_log /dev/stderr warn; server { listen 80; root /work/backend/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } server {(ここから追加で記述する) listen 443 ssl; root /work/backend/public; ssl_certificate /etc/certs/localhost.pem; ssl_certificate_key /etc/certs/localhost-key.pem; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } }docker-compose の起動
//コンテナをビルド make build = docker-compose build --no-cache --force-rm //コンテナを作成する make up = docker-compose up -d //全コンテナを起動する docker start $(dokcer ps -a -q) ⚠makefileがない場合はdockerコマンドを入力してください結果
下記のようにhttps通信ができました!
最近のブラウザはhttps通信を要求してくるので環境を整えて開発することをおすすめします
お読み頂きましてありがとうございました。
- 投稿日:2020-06-04T00:29:20+09:00
ローカル環境でnginxをhttps通信にする方法
はじめに
就活中の選考課題でGeolocation apiを使って、位置情報を利用するサイトを作る際に
Google chromeのブラウザでは、https通信しないと位置情報を取得できないので、
https通信をできるようにしました。
この記事は、ゆうきゃんさんの記事である最強のLaravel開発環境をDockerを使って構築する【新編集版】をベースにhttps通信を構築しています。1から環境を用意したい方は、上記の記事をはじめに参照してから本記事をご覧ください。開発環境
開発環境 Windows10 Home docker tool box 19.03.1 docker-compose 1.24.1 Mysql 8.0.20 Nginx 1.18.0 https通信する手順
Chocolateyのインストール
https通信に必要なSSL証明書を簡単に発行することができるmkcertというツールをインストールするために
Chocolateyというパッケージ管理ツールをインストールします①スタートメニューを右クリックしてコマンドプロンプトを管理者権限で開く
②コマンドか公式サイトからChocolateyインストール・コマンド C:\>Chocolatey Install Chocolatey v0.10.15C:\>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))`mkcertをインストールしてSSL証明書を発行
C:\>choco install mkcert C:\>mkcert localhost 196.168.99.101(ご自身のIPアドレスを入力) mkcert localhost 196.168.99.101 Using the local CA at "C:\Users\ユーザ名\AppData\Local\mkcert" Created a new certificate valid for the following names - "localhost" - "196.168.99.101(ご自身のIPアドレス)" The certificate is at "./localhost+1.pem" and the key at "./localhost+1-key.pem"発行したら今いるディレクトリに発行させるので
localhost+1.pem localhost+1-key.pemの+1を消して
docker-laravel\infrastructure\docker\nginxのディレクトリにファイルを移動します⚠もし、mkcert localhost 196.168.99.101(ご自身のIPアドレスを入力)と打って
システムリソース不足のため...と言われたら、
セキュリティーソフトのリアルタイムスキャンの停止や再起動をして見てくださいdocker-compose.ymlの記述
web: build: ./docker/nginx ports: - 196.168.99.101:80:80 - 196.168.99.101:443:443(ここを追加で記述する) volumes: - php-fpm-socket:/var/run/php-fpm - ../backend:/work/backendDockerfileの記述
FROM node:14.2-alpine as node FROM nginx:1.18-alpine SHELL ["/bin/ash", "-oeux", "pipefail", "-c"] ENV TZ=UTC RUN apk update && \ apk add --update --no-cache --virtual=.build-dependencies g++ COPY --from=node /usr/local/bin /usr/local/bin COPY --from=node /opt /opt COPY ./default.conf /etc/nginx/conf.d/default.conf ADD ./localhost.pem /etc/certs/localhost.pem(ここを追加で記述する) ADD ./localhost-key.pem /etc/certs/localhost-key.pem(ここを追加で記述する) WORKDIR /work/backenddefault.confの記述
access_log /dev/stdout main; error_log /dev/stderr warn; server { listen 80; root /work/backend/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } server {(ここから追加で記述する) listen 443 ssl; root /work/backend/public; ssl_certificate /etc/certs/localhost.pem; ssl_certificate_key /etc/certs/localhost-key.pem; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } }docker-compose の起動
//コンテナをビルド make build = docker-compose build --no-cache --force-rm //コンテナを作成する make up = docker-compose up -d //全コンテナを起動する docker start $(dokcer ps -a -q) ⚠makefileがない場合はdockerコマンドを入力してください結果
https://(ご自身のアドレス)を入力して接続すると下記のようにhttps通信ができました!
最近のブラウザはhttps通信を要求してくるので環境を整えて開発することをおすすめします
お読み頂きましてありがとうございました。