20200707のdockerに関する記事は13件です。

docker19.03で最速でGPU機械学習環境を作る

はじめに

nvidiaのGPUを使った機械学習の環境を整えたい。でも、なんか、面倒臭そう...
いえいえDockerを使えば簡単です。
下記のコマンドを使うと簡単に環境構築ができます。次に詳しく見ていきましょう。

docker run -v $PWD:/working -e DISPLAY=$DISPLAY --net host --gpus all --shm-size=8gb --name ml -it --workdir /working gcr.io/kaggle-gpu-images/python:v80 /bin/bash

コマンド説明

短いコマンドから徐々に引数を付け加えていき説明します。

このコマンドでまずkaggleのGPU版のイメージをコンテナとして実行します。

docker run /working gcr.io/kaggle-gpu-images/python:v80
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

k8s上にDockerプライベートレジストリ構築

開発してるとDockerのイメージをpushするところって迷うじゃないですか。
AWSで作っていればECR、GCPの場合にはGCRを使えばよいわけですが、家のサーバで開発しているときは?

まぁGCRやECRを使ってもよいのですが、近いところに欲しいですよね。
GCRを使う場合はこちらを参考にどうぞ。
オンプレのk8sのDockerレジストリにGCRを使う

Dockerのレジストリはhttpをしゃべるのでそんなに構築は難しくないみたいです。公式のDockerImageも用意されているのでそれを使えば一瞬さ?

でもk8sと同じサーバだと止まったときにデプロイできなくなるし、なんだかんだでせめて別サーバorクラウドなんじゃないかと、うっすら感じてはいる。

※httpsで通信できる必要があり〼。(insecureにすることでhttpでも可能ですが逆に面倒です。)

tl;dr

k8sのクラスタにDocker registryを展開して、そこにpush&k8sプロビジョニングします。

Docker registryをk8sのyamlで作成する。

ここに公式イメージがある。
https://hub.docker.com/_/registry
レジストリだけ。GUIはない。

k8s マニフェストyaml作成

registryのバージョンは2.7.1にした。ホストの/kube/docker-registry-data/var/lib/registryにマウントされる。
envで認証周りの環境変数を渡す。

docker-registry.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: docker-registry
  labels:
    app: docker-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: docker-registry
  template:
    metadata:
      labels:
        app: docker-registry
    spec:
      containers:
      - name: docker-registry
        image: registry:2.7.1
        env:
          - name: REGISTRY_AUTH
            value: htpasswd
          - name: REGISTRY_AUTH_HTPASSWD_PATH
            value: "/var/lib/registry/auth/htpasswd"
          - name: REGISTRY_AUTH_HTPASSWD_REALM
            value: "Registry Realm"
          - name: REGISTRY_HTTP_HOST
            value: "https://docker.deroris.net"
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: registry
          mountPath: /var/lib/registry
      volumes:
      - name: registry
        hostPath:
          type: Directory
          path: /kube/docker-registry-data
---
kind: Service
apiVersion: v1
metadata:
  name: docker-registry
spec:
  ports:
  - name: "http-port"
    protocol: TCP
    port: 80
    targetPort: 5000
  selector:
    app: docker-registry

htpasswdの設定

↑でhtpasswd形式の認証にしたので、htpasswdファイルを作成する。

注意 htpasswdファイルはbcryptオンリーで、registry:2.7からhtpasswdコマンドも同梱されなくなった模様。

適当なサーバでbcrypt形式のhtpasswdファイルを作成する。
リファレンス: https://httpd.apache.org/docs/2.4/programs/htpasswd.html

ホストのサーバでマウント先で直接作った。

[root@deroris auth]# pwd
/kube/docker-registry-data/auth
[root@deroris auth]# /usr/local/httpd/bin/htpasswd -cB ./htpasswd oreore
New password:
Re-type new password:
Adding password for user oreore
[root@deroris auth]# cat htpasswd
oreore:$2y$05$VVPZkdkwbBHdUlLfCEuWGO3UMVgdQ5HVgRNKoQ3HjKypJpFr6DhEO

リバプロの設定する。

手を抜いて一番フロントにいるApacheからk8sのServiceに直接続した。(良い子のみんなはやったらだめだぞ)
Ingress使っている人はちゃんとそれで設定してください。443に来たものをレジストリの80に流せばおkです。

# docker.deroris.net
<VirtualHost *:443>
    ServerName docker.deroris.net

    SSLEngine on
    SSLProxyEngine on
    SSLHonorCipherOrder on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite !3DES:!aNULL:EDH+HIGH:ECDH+HIGH:-AES128:-3DES:-DSS:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA
    SSLCertificateFile /etc/letsencrypt/live/deroris.net/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/deroris.net/privkey.pem

    ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPass / http://10.103.17.215/
    ProxyPassReverse / http://10.103.17.215/
    ProxyPreserveHost On
</VirtualHost>

別ホストからつながるか確認。とりあえずなんかかえってくればよかろう。

murata:~ $ curl https://docker.deroris.net/v2/
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}

push, pullできるか確認

動作確認しましょ。

docker login

別ホストからログイン

murata:~ $ docker login docker.deroris.net
Username: oreore
Password:
WARNING! Your password will be stored unencrypted in /home/murata/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

pull/push

適当なイメージをpullしてpush

murata:~ $ docker image pull fedora
Using default tag: latest
latest: Pulling from library/fedora
4c69497db035: Pull complete
Digest: sha256:ee55117b3058f2f12961184fae4b9c392586e400487626c6bd0d15b4eae94ecc
Status: Downloaded newer image for fedora:latest
docker.io/library/fedora:latest
murata:~ $ docker push docker.deroris.net/orega-fedora
The push refers to repository [docker.deroris.net/orega-fedora]
3b53a1a1ef4a: Pushed
latest: digest: sha256:829948d9a54ca9926c7fa01a976bbeccf38d66e85b558ca61f4b589246ab2d26 size: 529

これで上がっているはず。

ホストOSでディレクトリができているのが確認できる。

[root@deroris repositories]# pwd
/kube/docker-registry-data/docker/registry/v2/repositories
[root@deroris repositories]# ll
合計 0
drwxr-xr-x 5 root root 55  7月  7 18:34 orega-fedora
drwxr-xr-x 5 root root 55  7月  7 18:28 ubu
[root@deroris repositories]# ll orega-fedora/
合計 0
drwxr-xr-x 3 root root 20  7月  7 18:34 _layers
drwxr-xr-x 4 root root 35  7月  7 18:34 _manifests
drwxr-xr-x 2 root root  6  7月  7 18:34 _uploads

k8sにユーザー設定

ここまではただのDockerレジストリの構築。
k8sのデプロイで利用するにはk8sが↑のレジストリに接続できる必要がある。

これを参考にk8sにレジストリの認証情報を設定してみよう。
https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

適当にk8s用のdocker configを作る。configファイルをそのまま使うので、新しく作ったほうがいい。

╭─murata@deroris ~
╰─$ DOCKER_CONFIG=~/k8s-docker.config docker login docker.deroris.net
Username: oreore
Password:
WARNING! Your password will be stored unencrypted in /home/murata/k8s-docker.config/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

secretを作成する。

╭─murata@deroris ~
╰─$ kubectl create secret generic k8s-user \
    --from-file=.dockerconfigjson=/home/murata/k8s-docker.config/config.json \
    --type=kubernetes.io/dockerconfigjson
secret/k8s-user created

できてる。

╭─murata@deroris ~
╰─$ kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-8bwmk   kubernetes.io/service-account-token   3      119m
k8s-user              kubernetes.io/dockerconfigjson        1      48s

こんな感じで先ほどあげたイメージを上げてみよう。
imageに先ほどのレジストリのイメージを指定、imagePullSecretsにkubectl create secretした名前を入れる。

cat <<EOF | kubectl apply -f -
kind: Deployment
apiVersion: apps/v1
metadata:
  name: fedora
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fedora
  template:
    metadata:
      labels:
        app: fedora
    spec:
      containers:
      - args:
        image: docker.deroris.net/orega-fedora:latest
        imagePullPolicy: Always
        name: fedora
        command: ["sleep","3600"]
      imagePullSecrets:
        - name: k8s-user
EOF

ちゃんとfedoraちゃんのpodが動いている。

╭─murata@deroris ~
╰─$ kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/docker-registry-77599d7bc9-44rgv   1/1     Running   0          88m
pod/fedora-7c4d977b8f-v4cqj            1/1     Running   0          73s

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/docker-registry   ClusterIP   10.103.17.215   <none>        80/TCP    129m

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/docker-registry   1/1     1            1           129m
deployment.apps/fedora            1/1     1            1           73s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/docker-registry-695f6cfdfc   0         0         0       93m
replicaset.apps/docker-registry-75d44c887b   0         0         0       129m
replicaset.apps/docker-registry-77599d7bc9   1         1         1       95m
replicaset.apps/docker-registry-fd6788bb4    0         0         0       91m
replicaset.apps/fedora-7c4d977b8f            1         1         1       73s

describe してみてもちゃんと作ったイメージを使っているね。

╭─murata@deroris ~
╰─$ kubectl describe pod/fedora-7c4d977b8f-v4cqj
Name:         fedora-7c4d977b8f-v4cqj
Namespace:    reg-docker
Priority:     0
Node:         deroris.net/***.***.***.***
Start Time:   Tue, 07 Jul 2020 19:13:14 +0900
Labels:       app=fedora
              pod-template-hash=7c4d977b8f
Annotations:  cni.projectcalico.org/podIP: 10.244.0.73/32
              cni.projectcalico.org/podIPs: 10.244.0.73/32
Status:       Running
IP:           10.244.0.73
IPs:
  IP:           10.244.0.73
Controlled By:  ReplicaSet/fedora-7c4d977b8f
Containers:
  fedora:
    Container ID:  docker://8a8ef69c98bc56df757a83d7fc75cdbe45187310cfaf5eafa98817e914f6ce92
    Image:         docker.deroris.net/orega-fedora:latest
    Image ID:      docker-pullable://docker.deroris.net/orega-fedora@sha256:829948d9a54ca9926c7fa01a976bbeccf38d66e85b558ca61f4b589246ab2d26
    Port:          <none>
    Host Port:     <none>
    Command:
      sleep
      3600
    State:          Running
      Started:      Tue, 07 Jul 2020 19:13:15 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8bwmk (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-8bwmk:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8bwmk
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From                  Message
  ----    ------     ----  ----                  -------
  Normal  Scheduled  110s  default-scheduler     Successfully assigned reg-docker/fedora-7c4d977b8f-v4cqj to deroris.net
  Normal  Pulling    109s  kubelet, deroris.net  Pulling image "docker.deroris.net/orega-fedora:latest"
  Normal  Pulled     109s  kubelet, deroris.net  Successfully pulled image "docker.deroris.net/orega-fedora:latest"
  Normal  Created    109s  kubelet, deroris.net  Created container fedora
  Normal  Started    109s  kubelet, deroris.net  Started container fedora

終わりに。

  • proxyとしても動作できるようで、docker-hubのプロキシをローカルネットワーク内に置くこともできそう。
  • ストレージにはローカルのほかにs3やgcs, azureなども使える模様。
  • 認証の設定が入るので気軽に自前するのはよくないと思う。
  • ほんとはpv,pvcを使ったほうがいい。
  • 自身のk8sとは別のホストを使ったほうがいいと思う。

→あれ?GCRとかECR、せめてdocker-hub使ったほうがいいんじゃないかな・・・

ローカルのネットワーク内にたてる場合には、、、まぁあってもいいかもよ。。。

公式
https://docs.docker.com/registry/

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

Dockerコンテナ環境での開発で頻出するコマンドまとめ

はじめに

Dockerコンテナ環境で開発を進めていた際に、使う機会が多かったコマンド一式をまとめました。
本記事が皆様の一助になりますと幸いです。

docker-compose.ymlの変更を反映

イメージ: 再構築の必要なし
コンテナ: 再構築の必要あり docker-compose up -d

Dockerfileの変更を反映

イメージ: 再構築の必要あり docker-compose build
コンテナ: 再構築の必要あり docker-compose up -d

起動しているコンテナの停止・削除

全コンテナ停止: docker stop $(docker ps -q)
全コンテナ削除: docker rm $(docker ps -q -a)
全イメージ削除: docker rmi $(docker images -q)

参考文献

Docker Composeにおける各種ファイルの変更時の反映
https://qiita.com/subretu/items/5857628534b53f29f5a3
一発ですべてのDockerコンテナを停止・削除、イメージの削除をする
https://qiita.com/shisama/items/48e2eaf1dc356568b0d7

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

Dockerコンテナ環境における開発で頻出するコマンドまとめ

はじめに

Dockerコンテナ環境で開発を進めていた際に、使う機会が多かったコマンド一式をまとめました。
本記事が皆様の一助になりますと幸いです。

docker-compose.ymlの変更を反映

イメージ: 再構築の必要なし
コンテナ: 再構築の必要あり docker-compose up -d

Dockerfileの変更を反映

イメージ: 再構築の必要あり docker-compose build
コンテナ: 再構築の必要あり docker-compose up -d

起動しているコンテナの停止・削除

全コンテナ停止: docker stop $(docker ps -q)
全コンテナ削除: docker rm $(docker ps -q -a)
全イメージ削除: docker rmi $(docker images -q)

参考文献

Docker Composeにおける各種ファイルの変更時の反映
https://qiita.com/subretu/items/5857628534b53f29f5a3
一発ですべてのDockerコンテナを停止・削除、イメージの削除をする
https://qiita.com/shisama/items/48e2eaf1dc356568b0d7

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

【PHP】 Composer コマンドで tty を Docker につなげて開発したい(TTY as Interactive Shell/対話式シェルで tty)

composerscripts 設定で、composer dev と打ったら PHP の Docker コンテナを起動して触りたい。つまりコンテナにソースコードをマウントしてコンテナ内で開発・デバッグできる状態。

しかし、Interactive shell と表示され終了してしまう。Docker に限らず、他の対話式のシェル・スクリプトでも同じ。

「composer ユーザーコマンド 対話式 実行 tty interactive shell」でググってもドンピシャの Qiita 記事が出てこなかったので、自分のググラビリティとして。

TL; DR

[コマンド] < /dev/ttytty をコマンドとつなげる。

その際、Composer\\Config::disableProcessTimeout も設定しないと、composer制限で 300 秒で接続が切れてしまう

TS; DR

以下は3つのユーザー・コマンドを composer に設定している例です。

composer.json
{
    ...
    "scripts" :{
        "test": [
            "./vendor/bin/phpunit --configuration=./config/phpunit.xml"
        ],
        "compile": [
            "./vendor/bin/box compile --config=./config/box.json"
        ],
        "dev": [
            "Composer\\Config::disableProcessTimeout",
            "docker run --rm --entrypoint='/bin/bash' --workdir='/app' -v $(pwd):/app php:7-cli-alpine < /dev/tty"
        ]
    }
}

composer test コマンドで PHPUnit を使ってユニット・テストをローカルで実行。composer compile コマンドで Box3 を使って ./bin ディレクトリ設置用の Phar アーカイブの作成。そして composer dev コマンドで Docker の PHP7 コンテナを起動して対話式(bash シェル)で触れるようにしている例です。

この時、composer dev のメリットは、任意の PHP バージョンで Docker 上で実行できるので、Travis CI で回す前の簡易テストに便利です。

composer のユーザー・コマンド経由でターミナルの tty(入出力)を Docker に繋げるのがうまく行かなかったのですが、< /dev/tty によりターミナルの tty がコンテナに繋がるようになり、SSH した時のような操作感があるので便利です。

?   注意点
ターミナルの種類(macOS のターミナルなど)によってコンテナから exit すると tty 接続が壊れてターミナルを立ち上げ直さないといけない時があります。これは composer が使っている依存パッケージの symfonyconsole の仕様です。しかし、VSCode のターミナルからだと exit した以降でもローカルに戻ってきます(VSCode を立ち上げ直さなくても大丈夫です)。これは VSCode 側が、戻ってきたらターミナルを初期化をするからです。

参考文献

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

【PHP】 Composer コマンドで tty を Docker につなげて開発したい(Scripts, TTY and Interactive Shell)

composerscripts 設定で、composer dev と打ったら PHP の Docker コンテナを起動して触りたい。つまりコンテナにソースコードをマウントしてコンテナ内で開発・デバッグできる状態。

しかし、Interactive shell と表示され終了してしまう。Docker に限らず、他の対話式のシェル・スクリプトでも同じ。

「composer ユーザーコマンド 対話式 実行 tty interactive shell」でググってもドンピシャの Qiita 記事が出てこなかったので、自分のググラビリティとして。

TL; DR

[コマンド] < /dev/ttytty をコマンドとつなげる。

その際、Composer\\Config::disableProcessTimeout も設定しないと、composer制限で 300 秒で接続が切れてしまう

TS; DR

以下は3つのユーザー・コマンドを composer に設定している例です。

composer.json
{
    ...
    "scripts" :{
        "test": [
            "./vendor/bin/phpunit --configuration=./config/phpunit.xml"
        ],
        "compile": [
            "./vendor/bin/box compile --config=./config/box.json"
        ],
        "dev": [
            "Composer\\Config::disableProcessTimeout",
            "docker run --rm --entrypoint='/bin/bash' --workdir='/app' -v $(pwd):/app php:7-cli-alpine < /dev/tty"
        ]
    }
}

composer test コマンドで PHPUnit を使ってユニット・テストをローカルで実行。composer compile コマンドで Box3 を使って ./bin ディレクトリ設置用の Phar アーカイブの作成。そして composer dev コマンドで Docker の PHP7 コンテナを起動して対話式(bash シェル)で触れるようにしている例です。

この時、composer dev のメリットは、任意の PHP バージョンで Docker 上で実行できるので、Travis CI で回す前の簡易テストに便利です。

composer のユーザー・コマンド経由でターミナルの tty(入出力)を Docker に繋げるのがうまく行かなかったのですが、< /dev/tty によりターミナルの tty がコンテナに繋がるようになり、SSH した時のような操作感があるので便利です。

?   注意点
ターミナルの種類(macOS のターミナルなど)によってコンテナから exit すると tty 接続が壊れてターミナルを立ち上げ直さないといけない時があります。これは composer が使っている依存パッケージの symfonyconsole の仕様です。しかし、VSCode のターミナルからだと exit した以降でもローカルに戻ってきます(VSCode を立ち上げ直さなくても大丈夫です)。これは VSCode 側が、戻ってきたらターミナルを初期化をするからです。

参考文献

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

AWSのECSでコンテナにWEBターミナル接続

ECSを使用するとデバッグ環境でコンテナに接続するのが面倒なので、コンテナにWebターミナルであるGoTTYを入れてみる方法を考えてみました。
あくまでもデバッグ目的で使用します。

自分のアプリのDockerファイルにgottyを設定

Dockerfileのgotty設定部分 (alpineを使用しています)

# GoTTY
RUN addgroup -S gotty && adduser -S -g gotty gotty \
    && mkdir -p /gotty \
    && chown -R gotty /gotty && chgrp -R gotty /gotty
RUN wget -qO- https://github.com/yudai/gotty/releases/download/v0.0.12/gotty_linux_amd64.tar.gz | tar zx -C /gotty/
RUN echo 'port = "8080"' >> /home/gotty/.gotty
RUN echo 'credential = "myacc:pass"' >> /home/gotty/.gotty
RUN chown -R gotty /gotty/gotty /home/gotty

# Supervisor
RUN echo '[supervisord]' >> /etc/supervisord.conf
RUN echo 'nodaemon=true' >> /etc/supervisord.conf
RUN echo '[program:myapp]' >> /etc/supervisord.conf
RUN echo 'command=/myworks/myapp'   >> /etc/supervisord.conf
RUN echo '[program:gotty]' >> /etc/supervisord.conf
RUN echo 'command=/gotty/gotty --config "/home/gotty/.gotty" -w /bin/ash' >> /etc/supervisord.conf
RUN echo 'autostart=true' >> /etc/supervisord.conf
# RUN echo 'user=gotty' >> /etc/supervisord.conf

EXPOSE 80 8080

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

portでターミナルのポート
credentialでベーシック認証のアカウントとパスワード
ただ確認したいだけであれば"user=gotty"の部分のコメントを外してください。

ECSのタスク定義

コンテナから自分のアプリの80とターミナルの8080を通したいのですが、私が使用していたecs-cliのバージョンではマルチポートの設定がうまくできなかったのでawsクライアントでタスク定義からやります。
targetGroupArnは自分のターゲットグループARNを入れてください。

  • ポート定義ファイル"multiport.json"を作成
{
"loadBalancers": [
{
"containerName": "myapp",
"containerPort": 80,
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:*********:targetgroup/mycluster/*****"
},
{
"containerName": "myapp",
"containerPort": 8080,
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:*********:targetgroup/mycluster/****"
}
]
}
  • タスク定義ファイル"task-definition.json"を作成
{
    "memory": "512", 
    "networkMode": "bridge", 
    "family": "mytask", 
    "placementConstraints": [], 
    "cpu": "256", 
    "executionRoleArn": "arn:aws:iam:*************", 
    "volumes": [], 
    "requiresCompatibilities": [
        "EC2"
    ], 
    "taskRoleArn": "arn:aws:iam::*************", 
    "containerDefinitions": [
        {
            "links": [], 
            "image": "********.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/develop:1.0.0", 
            "hostname": "myhost", 
            "environment": [
            ], 
            "extraHosts": [], 
            "dnsServers": [], 
            "volumesFrom": [], 
            "dnsSearchDomains": [], 
            "mountPoints": [], 
            "logConfiguration": {
                "logDriver": "awslogs", 
                "options": {
                    "awslogs-region": "ap-northeast-1", 
                    "awslogs-stream-prefix": "docker", 
                    "awslogs-group": "/myapp/group"
                }
            }, 
            "dockerSecurityOptions": [], 
            "entryPoint": [], 
            "linuxParameters": {
                "devices": [], 
                "capabilities": {}
            }, 
            "essential": true, 
            "readonlyRootFilesystem": false, 
            "name": "myapp", 
            "dockerLabels": {}, 
            "privileged": false, 
            "portMappings": [
                {
                    "protocol": "tcp", 
                    "containerPort": 80, 
                    "hostPort": 0
                }, 
                {
                    "protocol": "tcp", 
                    "containerPort": 8080, 
                    "hostPort": 8080
                } 
            ], 
            "command": [], 
            "cpu": 0, 
            "ulimits": []
        }
    ] 
}

タスクの定義とECSサービス起動

revision=`aws ecs register-task-definition --cli-input-json file://task-definition.json | jq '.taskDefinition.revision'`
echo "revision:${revision}"
aws ecs create-service --cluster ${CLUSTER_NAME} --service ${SERVICE_NAME} --task-definition mytask:${revision} --deployment-configuration maximumPercent=${MAX_PARCENT},minimumHealthyPercent=${MIN_PARCENT} --desired-count 1 --launch-type EC2 --cli-input-json file://multiport.json

ブラウザでアクセス

指定した8080ポートにブラウザでアクセスするとターミナルが立ち上がります。

gotty.png

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

Docker&Rails6の環境を構築してみる。

本記事について(お断り)

この記事は、しがないプログラミング初心者がお勉強よろしくプログラミング・技術に触れるべく、行ったことの備忘録として書き綴ったものです。ご了承ください。
ご指摘は甘んじて受け入れます?‍♂️

目的

ここではひとまず自分で必要なファイルの準備から、Railsのアプリケーションを起動できるまでを目指します。

参考

今回の作業は下記の記事を参考にさせていただいてます。とても勉強になりました。ありがとうございます。
Quickstart: Compose and Rails | Docker Documentation
https://qiita.com/kodai_0122/items/795438d738386c2c1966#2-2-bundle-install
https://qiita.com/at-946/items/2fb75cec5355fad4050d

環境構築手順

1.準備

1-1フォルダの作成

まずは作業を行うためのフォルダを任意に作成します。
作成したフォルダに移動しておきます。

$ mkdir myapp
$ cd my app

1-2Dockerfileの作成

フォルダ内にDockerfileを作成します。
公式ページ内:クイックスタートを参考にバージョンだけ変えて作成しました。

Dockerfile
FROM ruby:2.6.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# 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"]

1−3Gemfileの作成

ここではインストールするRailsのバージョンを6に指定します。あわせてGemfile.lockも作成しておきます。中身は何も書かなくてOKです。

Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'
$ touch Gemfile.lock

1-4entrypoint.shの作成

コンテナが起動した時に、Railsのserver.pidを毎回削除してくれる様です。(英語得意ではないので書いてあること違ってたらすいません)よくこのファイルが残っててコンテナの中身を消しにいくの大変だった思い出。

entrypoint.sh
#!/bin/bash
set -e

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

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

1-5docker-compose.ymlの作成

docker-compose.ymlは、魔法の様なファイルです。必要なアプリ(web、dbアプリ)を構成するサービスやそのイメージをまとめて実行してくれます。(英語得意ではないn自分がこのファイルを使ってみての感覚で話してるとこもあるので、誤解を招く様な表現があったらすみません)

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

ここでは、DB(PostgreSQL)、webの二つを実行してもらう様記載します。

ここまでできたら、ファイルの準備は完了です。

2.プロジェクトのビルド

2-1rails new

docker-compose run コマンドを使って、rails newしていきます。

$ docker-compose run web rails new . --force --no-deps --database=postgresql --skip-bundle

これで、myappフォルダの中に見慣れたフォルダ構成ができてきます。
ターミナルの最後で、以下の様にメッセージを出してきます。

Could not find gem 'pg (>= 0.18, < 2.0)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.

bundle installしてねというメッセージでした。

2-2bundle install

Dockerfileでbundle installする様記述してあるため、イメージをビルドする際に勝手にやってくれます。

$ docker-compose build

2-3DB接続設定

Railsのconfg/database.ymlを、以下に書き換えます。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
.
.
.

2-4Dockerコンテナ起動

$ docker-compose up

するとなんだか色々エラーだと言われました。

db_1   | Error: Database is uninitialized and superuser password is not specified.
.
.
.
web_1  | /usr/local/bundle/gems/webpacker-4.2.2/lib/webpacker/configuration.rb:95:in `rescue in load': Webpacker configuration file not found /myapp/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /myapp/config/webpacker.yml (RuntimeError)

上のエラーは、PostgreSQLのパスワードが必要なために出てきたメッセージです。confg/database.ymlに追記しておきます。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password  # <= この部分
  pool: 5

もう一つのエラーは、Rails6からWebpackerがデフォルトで導入されるため、Webpackerのインストールを求めるものでした。
で、そのWebpackerのインストールにはyarnやNode.jsのインストールが必要だそうです。

それらに対応するため、Dockerfileを編集する必要があります。

Dockerfile
FROM ruby:2.6.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
# yarnインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget
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 && apt-get install -y yarn
# Node.jsインストール
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
  apt-get install nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# 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"]

それではWebpackerをインストールしてみます。

$ docker-compose stop
$ docker-compose down
$ docker-compose run web bundle exec rails webpacker:install
.
.
Webpacker successfully installed ? ?

無事Webpackerのインストールに成功しました。
もう一度、コンテナを起動します。

$ docker-compose up

2-5DB作成

DBを作成します。これで完了です。

$ docker-compose run web rails db:create
Starting myapp_db_1 ... done
Created database 'myapp_development'
Created database 'myapp_test'

2−6アクセスしてみる
ブラウザでhttp://localhost:3000/にアクセスしてみます。お馴染みの画面が出迎えてくれ無事成功しました!

Rails6.png
Yay!

まとめ

DockerでRails6の環境を作成してみました。
実際やってる時は、作業フォルダの名前とDockerfileに指定しているフォルダ名が違ったりして、色々と他にも手こずってました。他の方の一助になれば幸いです。

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

Docker(Djnago)をHerokuへデプロイする方法

Dockerコンテナ上で開発したDjangoをHerokuにデプロイするにはいくつか方法があります。

1、Djnagoソースのみをデプロイする。
2、docke buildでimageをビルドしてHerokuにデプロイする。
3、herokuのコマンドでimageのビルドとデプロイを行う。
etc...

今回は3の方法を使ってデプロイしたいと思います。

まず、DockerImageをアップするレジストリにログインします。
このとき--passwordにHEROKU_API_KEYを指定すればusernameは"_"にすることができます。

$ docker login --username "_" --password "$HEROKU_API_KEY" registry.heroku.com

次にheroku containerへもログインしておきます。

$ heroku container:login

DockerImageのビルドをレジストリへのpushを行います。
引数に設定しているwebはherokuのプロセスタイプです。
--appオプションにHerokuのapp名を指定します。

$ heroku container:push web --app HEROKU_APP_NAME

最後にpushしたDockerImageをHerokuにリリースしてます。
これを行うことでHerokuへデプロイされます。

$ heroku container:release web --app HEROKU_APP_NAME

DockerfileにCMDを指定しておけばデプロイ後に実行されます。

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

Docker rakeタスクをcron実行したい

rakeタスクをcronで動かせない

前回の記事では、CronをDocker上で動かす方法を紹介しました。
CronをDocker上で動かす

今回は前回の方法とは違いますが、rakeタスクのcron実行に手こずったところと、解決方法を紹介していきます。

前回はDocker環境でcronを動かすなら、busyboxを使用することをおすすめしていました。
しかし、私の環境ではrakeタスクをcron実行する際に起きた問題がありました。

cron実行時(busyboxコンテナでのコマンド実行)に、以下のエラーが発生しました。

PG::ConnectionBad: could not translate host name "db" to address: Name or service not known

busyboxコンテナが、dbコンテナと疎通できていない!

試したこと

  • そもそもdbコンテナは立ち上がっているか確認 → upになってる。
  • postgresコンテナに環境変数POSTGRES_PASSWORDを設定する。その値をconfig/database.ymlのpasswordに定義する。
  • database.ymlの書き換え。
database.yml
default: &default
 host: localhost

host: dbとなっていた部分を、host: localhostに変更しました。
これを行うと、

could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

というエラーの内容に変わります。
これに対して、

  • pgの再インストール
  • pgの起動確認・rake db:create
    を実行するも、エラーの内容に変わりありませんでした。
    ちなみに、rake db:createはhost:dbのまま実行すれば、問題なかったです。
    webも問題なく動いています。

  • busyboxのコンテナも、dbコンテナが起動している必要がある構成になっているので、depends_onを付けてみる。

docker-compose.yml
  busybox:
    build: .
    volumes:
      - ./crontab:/var/spool/cron/crontabs/root
    depends_on:
      - db

しかし、同じエラーが出現してしまい、状況は変わりませんでした。

その他色々と試行錯誤した結果、結局busyboxコンテナをdbコンテナと疎通することができませんでした。(完全に力不足です。2週間悩みましたが解決には至らず...。)

そこで解決までに至ったのが、Dockerのimage内でcronをinstallし、cronを実行する方法です。

Docker-compoeのコンテナ内でcronを動かす方法

こちらの記事を参考にさせていただきました。
docker-composeのコンテナ内でcronを動かす

インストール手順

  • Dockerコンテナの中に入る
docker exec -i -t myapp_web_1 bash
  • cronをinstall
# apt-get install cron
  • editorのinstall
# apt-get install vim
  • crontab -eで編集

※ 環境変数を設定する記述がなければ、エラーになります。(私の場合、gemやpathなどの環境変数の設定も必要でした。)
※ 環境変数の値は、printenvで確認できます。
※ ruby実行時に、「/usr/bin/env: 'ruby': No such file or directory」というエラーが出現してしまうことを防ぐために、以下を設定します。
rbenvにのせたrubyを使うためのパス設定を~/.bash_profileにしておく。
これをcrontabからの実行でも読み込まれるよう、crontabにbash経由で実行するよう設定。
【参考記事】
https://normalblog.net/system/cron-ruby-command-not-found/#i
https://normalblog.net/system/install/

RUBY_VERSION=2.6.5
BUNDLE_APP_CONFIG=/usr/local/bundle
RUBY_MAJOR=2.6
GEM_HOME=/usr/local/bundle
PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RAILS_ENV=development
* * * * * /bin/bash -l -c 'cd /myapp/lib/tasks && bundle exec rake notify_user_mailer:notify_user_mail >>/var/log/cron.log 2>&1'

毎分、全てのユーザーに対してメールを送信するという定期実行を設定しています。

  • cron起動
# service cron start

すると1分ごとに全てのユーザーにメールが届いており、
見事rakeタスクのcron実行に成功しました!

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

SAM CLI の Docker内(--use-container) ビルドをでProxy環境下で実施する方法

SAMでは、Lambdaと近い環境でビルドできる

SAM(Serverless Application Model) CLI のビルドコマンド(sam build)には、
Lambda用の npmpip などで、アーキテクチャ(WindowsかLinux等)に依存するモジュールが有る場合に対応する
オプション (--use-container)がある。

このオプションを使用すると、通常、実行環境(windows等)で行うビルド処理を、Lambda(Amazon Linux) に近い
Docker環境内で行うようなるため、コンパイルを伴うようなモジュールでも問題なく、Lambda用のリソースを作成することが可能となる。

Proxyの憂鬱

ここにも、毎度同じみのProxyの憂鬱がある。

実行環境が、Proxy経由でインターネットに繋がっている場合、
当然、Docker内からもProxy経由でしかインターネットに繋ぐことが出来ない為、
Docker インスタンスに対して、環境変数等でProxy設定を与えてあげる必要がある。

しかし、SAM のビルドコマンド(sam build)で、実行する場合、動的にインスタンスを作成し
ビルドが終了すると動的に削除する為、Proxyを与えることが難しかった。

※Docker Desktopのproxy設定は、Docker Imageをダウンロードする際に使用するProxy設定で、Docker Image内には適用されない。

そこで、SAM では、 Docker SDK >= 3.7.0 でサポートされた、
global docker configuration file. 機能を使って、
外部からProxy設定を可能にするよう対応している。

既に、上記のPull Request は、マージされてReleaseされているが、
特にドキュメントには残されていない為、見つけにくいので、ここに書き残したいと思います。

global docker configuration file.

設定方法は、以下の記事 @2fbCvmiYKX さんの記事や Dockerのドキュメントが詳しいが、

%USERPROFILE%\.docker\config.json の編集し

変更前
{
  "auths": {
    "https://index.docker.io/v1/": {}
  },
  "credsStore": "desktop",
  "experimental": "enabled",
  "stackOrchestrator": "kubernetes"
}

を以下のように修正する

変更後
{
  "auths": {
    "https://index.docker.io/v1/": {}
  },
  "credsStore": "desktop",
  "experimental": "enabled",
  "stackOrchestrator": "kubernetes",
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:8080",
      "httpsProxy": "http://proxy.example.com:8080",
      "noProxy": "no_proxy.example.com"
    }
  }
}

これで、以下の通り、Proxy環境下であっても、SAM CLI の Docker内(--use-container) ビルドを実施することが、可能となる。

PS C:\Users\komikoni\workspace\sam app> sam build --use-container

Starting Build inside a container
Building function 'AuthFunc'
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Fetching lambci/lambda:build-nodejs12.x Docker container image......
Mounting C:\Users\komikoni\workspace\sam app\node-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building function 'NodeFunc'

Fetching lambci/lambda:build-nodejs12.x Docker container
image..............................................................................................................................................................................................................
Mounting C:\Users\komikoni\workspace\sam app\node-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building function 'PythonFunc'
//./pipe/docker_engine
//./pipe/docker_engine

Fetching lambci/lambda:build-python3.6 Docker container image..............................................................................................................................................................................................................
Mounting C:\Users\komikoni\workspace\sam app\python-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Build Succeeded

Built Artifacts  : .aws-sam\build
Built Template   : .aws-sam\build\template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
PS C:\Users\komikoni\workspace\sam app> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SAM CLI の Docker内(--use-container) ビルドをProxy環境下で実施する方法

2017年頃からサーバレスに浸っている、小西啓介です。

image.png

SAMでは、Lambdaに近い環境でビルドできる

SAM(Serverless Application Model) CLI のビルドコマンド(sam build)には、
Lambda用の npmpip などで、アーキテクチャ(WindowsかLinux等)に依存するモジュールが有る場合に対応する
オプション (--use-container)がある。

このオプションを使用すると、通常、実行環境(windows等)で行うビルド処理を、Lambda(Amazon Linux) に近い
Docker環境内で行うようなるため、コンパイルを伴うようなモジュールでも問題なく、Lambda用のリソースを作成することが可能となる。

Proxyの憂鬱

ここにも、毎度おなじみのProxyの憂鬱がある。

PS C:\Users\komikoni\workspace\sam app> sam build --use-container

Building function 'NodeFunc'
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Fetching lambci/lambda:build-nodejs12.x Docker container image......
Mounting C:\Users\komikoni\workspace\sam app\node-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Build Failed
Error: NodejsNpmBuilder:NpmInstall - NPM Failed: npm ERR! code ENOTFOUND
npm ERR! errno ENOTFOUND
npm ERR! network request to https://registry.npmjs.org/jsonwebtoken failed, reason: getaddrinfo ENOTFOUND registry.npmjs.org
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'

npm ERR! A complete log of this run can be found in:

実行環境が、Proxy経由でインターネットに繋がっている場合、
当然、Docker内からもProxy経由でしかインターネットに繋ぐことが出来ない為、
Docker インスタンスに対して、環境変数等でProxy設定を与えてあげる必要がある。

しかし、SAM のビルドコマンド(sam build)で、実行する場合、動的にDockerインスタンスを作成し
ビルドが終了すると自動的に削除される為、Proxyを与えることが難しかった。

※Docker Desktopのproxy設定は、Docker Imageをダウンロードする際に使用するProxy設定で、Docker Image内には適用されない。

この課題は、以下のIssueに上がっている。

そこで、SAM では、 Docker SDK >= 3.7.0 でサポートされた、global docker configuration file. 機能を使って、
外部からProxy設定を可能となるよう対応が行われた。

既に、上記のPull Request は、マージされてReleaseされているですが、
特にドキュメント上には、記載がなさそうなので、ここに書き残したいと思います。

global docker configuration file の設定

設定方法は、以下の記事 @2fbCvmiYKX さんの記事や Dockerのドキュメントが詳しいが、

%USERPROFILE%\.docker\config.json の編集し

変更前
{
  "auths": {
    "https://index.docker.io/v1/": {}
  },
  "credsStore": "desktop",
  "experimental": "enabled",
  "stackOrchestrator": "kubernetes"
}

を以下のように修正する

変更後
{
  "auths": {
    "https://index.docker.io/v1/": {}
  },
  "credsStore": "desktop",
  "experimental": "enabled",
  "stackOrchestrator": "kubernetes",
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:8080",
      "httpsProxy": "http://proxy.example.com:8080",
      "noProxy": "no_proxy.example.com"
    }
  }
}

これで、以下の通り、Proxy環境下であっても、SAM CLI の Docker内(--use-container) ビルドを実施することが、可能となる。

PS C:\Users\komikoni\workspace\sam app> sam build --use-container

Starting Build inside a container
Building function 'AuthFunc'
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Fetching lambci/lambda:build-nodejs12.x Docker container image......
Mounting C:\Users\komikoni\workspace\sam app\node-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building function 'NodeFunc'

Fetching lambci/lambda:build-nodejs12.x Docker container
image..............................................................................................................................................................................................................
Mounting C:\Users\komikoni\workspace\sam app\node-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building function 'PythonFunc'
//./pipe/docker_engine
//./pipe/docker_engine

Fetching lambci/lambda:build-python3.6 Docker container image..............................................................................................................................................................................................................
Mounting C:\Users\komikoni\workspace\sam app\python-function as /tmp/samcli/source:ro,delegated inside runtime container
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine
//./pipe/docker_engine

Build Succeeded

Built Artifacts  : .aws-sam\build
Built Template   : .aws-sam\build\template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
PS C:\Users\komikoni\workspace\sam app> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ArchLinuxでDocker使うと、コンテナ内で生成したファイルがrootになる問題

英語読んで書いてあることやっただけ。

状況

  • ホストマシンがLinuxでDockerを使う場合、rootで実行する必要ある
    → いちいち sudo docker-compose とsudoする必要あり
    → コレについてはzshでalias張れば解決なのでまぁ、大丈夫

  • コンテナ内で自動生成する場合 (Laravelとかでファイルを生成させる場合とか)
    → 生成されるファイルが root:root になる
    → Read onlyになって触れないので、いちいち sudo chown する必要が

これを解決したい

Rootlessモード

この問題には userns-remap という解決方法があったが、
Docker v19.03からは rootlessモード というものが用意されたようで、こちらを使ってみようと思う。

この違いとしては、 userns-remap デーモン自体はrootで動いていたのに対し、
Rootlessモードではすべてがroot権限なしで動くようになっている様子。
(ただしまだ動かないものもあるらしい)

環境

  • ArchLinux
  • yay (AUR)

インストール

https://docs.docker.com/engine/security/rootless/

一応、Dockerの公式には乗ってるらしいが、ArchLinuxのユーザリポジトリ(AUR)に方法が載っていたので、
AURで楽しようと思う。

20/07/06 ぐらいの話なので、AURのページから下記の情報がまだ使えるか確認しながらどうぞ。

https://aur.archlinux.org/packages/docker-rootless/#pinned-724406

docker-rootlessをAURからインストール

上記に従ってまず AUR から docker-rootless をいれてやる

$ yay -S docker-rootless

終わったらこの表示が出る。これは先程のAURのコメントの通りなので、これに従ってやっていく

=== Post installation message from docker-rootless ===
This is based on https://docs.docker.com/engine/security/rootless/                   
To Run the Docker daemon as a non-root user (Rootless mode) for ArchLinux, you need t
o do the following things:                                                           

1. configure kernel settings                                                         

create '/etc/sysctl.d/99-docker-rootless.conf': 'kernel.unprivileged_userns_clone=1'

and then run: 'sudo sysctl --system'

> see https://docs.docker.com/engine/security/rootless/#distribution-specific-hint for detailed information                    

2. configure subuid and subgid

and create '/etc/subuid' and '/etc/subgid' with: 'testuser:231072:65536' (for example
, 'testuser' is username)                 

> see https://docs.docker.com/engine/security/userns-remap/#prerequisites for detailed information        

3. start and enable user service: 'systemctl --user status|start|stop docker'

4. finally set docker socket environment variable: 'export DOCKER_HOST=unix://$XDG_RU
NTIME_DIR/docker.sock', you can also add it to '~/.bashrc' or somewhere alike
=========

カーネルの設定

以下を作る

/etc/sysctl.d/99-docker-rootless.conf
kernel.unprivileged_userns_clone=1

subuid, subgid の設定

それぞれ下記内容で生成
ユーザ名には自分のユーザ名を

/etc/subuidと/etc/subgid
ユーザ名:231072:65536

ユーザのDocker起動,自動起動有効

# まず状態の確認
$ systemctl --user status docker
# State が running でなければ start
$ systemctl --user start docker
# 自動起動を有効に
$ systemctl --user enable docker

enableした場合、設定が最後まで終わったあと再起動してdockerが起動されているか確認すると良さそう

Docker Host

お使いのshellでPATHを通す
私は zsh

.zshrc
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

再起動

あとはユーザ権限で docker info ができるかどうか。
できたらおめでとう :tada:

注意

rootless な Docker は、sudo で起動するものとは別にコンテナなどを持つので、
つまり同じプロジェクトでもdocker-compose up -dすると新しくbuildが走っちゃうよ、ということである
新幹線でテザリングしてたらコンテナビルド走って慌てて消した (1GBぐらいは落としてしまってた

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