- 投稿日:2020-07-25T23:44:53+09:00
C言語 と Dart で CGI : はじめに (1)
C言語 と Dart で CGI
昨今は動的なホームページを作成する場合には、「VPS で Linux インスタンスを立ち上げたり」、「Serverless の フレームワークを利用してコンテンツを配信したり」、「K8Sなどを利用してContainer に落としたり」するのが最近のトレンドだと思います。
が、つい最近まで、レンタルサーバーを借りてCGIを利用して動的コンテンツを配信するのが一般的でした。
この、CGIについて解説して行きます。C言語とDart言語からCGIを利用
また、CGIと言えば、Perl や PHP などが、良く使われますが、
ここでは、C言語とDart言語を対象とします。Dart言語 で CGI に利用した話が、DuckDuckGoしてもGoogleしても皆無だったからです。
※ 訂正: C言語はあります!! Dartが皆無もちろん、皆無だった理由はクラシックな技術で、
今後、利用される事もなかったからでしょうCGIはシンプルで容易
2004-2006年くらいでしょうか? PHP が 広まり、多くのサービスがCGIで作られました。
非エンジニアの人も多く。そんな非エンジニアの方々でも
全体像を把握出来、お金を稼ぐようなサービスが作られて行きました。昨今の、React Vue Flutter や Firebase た Lambda など Serverless と比較して
習得が容易だったからだと考えています。CGI とは
CGIは、Common Gateway Interface の略です。
https://en.wikipedia.org/wiki/Common_Gateway_Interface
https://tools.ietf.org/html/rfc3875特にサーバーと外部のプログラムの間での、やりとり方法を決めたものです。
今時のInterface と違い 超シンプルです。サーバーからアプリを起動して、実行結果をもらう
CGIでは、サーバーからパラメータを指定してアプリを起動します。
そのアプリが出力する標準出力をを返り値としてもらう。具体的に見てみましょう。
Hello,World!! と表示するアプリ
hello.c// hello.c // gcc hello.c -o hello.cgi #include<stdio.h> int main(int argc, char* argv[]) { printf("Content-type: text/html\n\n"); printf("Hello,World!!\n"); return 0; }という、hello.cgi という名前のアプリがあるとします。
このアプリは、./hello.cgi
とコマンドを入力すると、
"""
Content-type: text/htmlHello,World!!
"""
と、コンソールにも文字列を表示するだけのアプリです。Hello,World!! と表示するページになる
ブラウザーから、 "http://example.com/hello.cgi" を呼び出すと、
"Hello,World!!" とブラウザーに表示されます。このように、サーバーからアプリを呼び出して
アプリからの出力をユーザーに返すという事がCGIでは出来ます実際に動かしてみよう
Docker 環境を用意しました。
細かな設定とかはDockerファイルを参照してください!!Container を起動
$ git clone https://github.com/kyorohiro/dartlang_cgi.git $ cd ./dartlang_cgi/001 $ docker-compose build $ docker-compose up -dVSCodeを起動
ブラウザーでDocker Container の 中の VSCode を開く
http://127.0.0.1:8443
※ 127.0.0.1 は Dockerの環境依存です。vscode の中で、Apacheサーバーの立ち上げ
$ apache2cgiをビルド
$ cd /app/www/cgi $ gcc hello.c -o hello.cgi $ dart2native hello_dart.dart -o hello_daet.cgi動作確認
http://127.0.0.1:8080/ を開くと、 ./app/www/index.html が表示されます
http://127.0.0.1:8080/cgi-bin/hello.cgi を開くと。./app/cgi/hello.cgi の実行結果が返ります
http://127.0.0.1:8080/cgi-bin/hello_dart.cgi を開くと、 ./app/cgi/hello_dart.cgi の実行結果が返ります
補足
Dart は dart2native を利用する事で、Nativeにコンパイル出来ます。
今回はそれを使用しています。main(List<String> args) { print("Content-type: text/html\n\n"); print("Hello,World From Dart!!\n"); return 0; }コード
https://github.com/kyorohiro/dartlang_cgi
次回
GET や POST や Cookie や
DB を扱ってみます。
- 投稿日:2020-07-25T21:52:44+09:00
DockerでTypeScript+Reactな環境構築(create-react-app)
目標
- Dockerとdocker-composeを用いてcreate-react-appし、Reactアプリケーションの開発を始められる
- かつ、TypeScriptでReactを動かす
前提
- Dockerが使用可能である
- docker-composeが使用可能である
手順
1. 作業ディレクトリの作成
作業するディレクトリを作成しましょう。
プロジェクト名はここではsample-app
とします。% mkdir sample-app % cd sample-app
2. Dockernize
Dockerfileとdocker-compose.ymlを作成し、中身を追加します。
% touch Dockerfile % touch docker-compose.yml
nodeのバージョンはこちらから新しめのものを選択すればいいと思います。
プロジェクトディレクトリ名が"sample-app"なので、コンテナ名・react-app名は"frontend"とします。
DockerfileFROM node:14.4.0-alpine3.10 ENV LANG=C.UTF-8 ENV TZ=Asia/Tokyo WORKDIR /usr/src/sample-appdocker-compose.ymlversion: '3' services: frontend: build: . environment: - NODE_ENV=development volumes: - ./:/usr/src/sample-app command: sh -c 'cd frontend && yarn start' ports: - '3000:3000' tty: true
volumes
:ホスト:コンテナ
間でファイル・ディレクトリを同期(= マウント)する
- これにより、ホスト側のエディター等で行った編集がコンテナ側にも反映されたり、
docker-compose run コマンド
でコンテナ側に生成されたファイル・ディレクトリがホスト側にも同様に生成されるようになるsh -c 'cd frontend && yarn start'
:docker-compose up
したとき、react-appディレクトリに移動し、devサーバーを起動するports
: 公開用のポートを、'ホスト:コンテナ'
の書式で指定している。
- ブラウザでローカルホストを開くときはホスト側に指定したポートを参照する(e.g. この場合、ブラウザからは
localhost:3000
で開発環境のアプリケーションにアクセスできる)tty
: 値をtrueにすることで、docker-compose up
でコンテナを起動させた際にコンテナがすぐに終了してしまうのを防ぐ3. ビルド
% docker-compose build % docker-compose run --rm frontend sh -c 'npx create-react-app frontend --template typescript'
--rm
: コマンド実行後にこのコンテナ(frontend)を削除する--template typescript
: .jsxファイルの代わりに.tsxファイルが生成され、ReactアプリケーションがTypeScriptで動くようになる正常にビルドが完了した場合、以下のようなディレクトリ構成になります。
TSXファイル等はsrc
以下に配置されています。sample-app ├── Dockerfile ├── docker-compose.yml └── frontend ├── node_modules ├── public ├── src ├── .gitignore ├── README.md ├── package.json ├── tsconfig.json └── yarn.lock
4. アプリケーション起動の確認
下記コマンドでdevサーバーが起動します。
% docker-compose up
http://localhost:3000/
にアクセスし、App.tsx
の内容が表示されていれば成功です。
該当ファイルをエディターで編集するとすぐに反映されることも確認できるはずです。あとは自由に開発を進めていきましょう!
アプリケーションの停止は下記コマンドでできます。
% docker-compose down
参考
- 投稿日:2020-07-25T20:31:41+09:00
Docker 環境別 no cache install
docker cache clean clear
基本的には、multi-stage-buildを用いて、build用のimageと成果物のimageを分けることが望ましい。
installされたpackageが多数のディレクトリにまたがっていたり、それが難しいケースはbase imageのパッケージ管理ツールのclean機構をonelinerで書くと良い。apt
DockerfileFROM debian RUN apt-get update && apt-get install -y \ * \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*参考: https://docs.docker.jp/engine/articles/dockerfile_best-practice.html#run
npm
DockerfileFROM node RUN npm install -g \ * \ && npm cache clean --force参考: https://qiita.com/hikaruna/items/0bc1e97e8d254f4c27e7
yarn
TODO
yum
TODO
pip
TODO
- 投稿日:2020-07-25T19:21:38+09:00
[Docker] Rootless Docker を試してみた
Rootless Docker とは
Rootless モード(Rootless mode)は Docker デーモンとコンテナを root 以外のユーザが実行できるようにするもので、デーモンやコンテナ・ランタイムにおける潜在的な脆弱性を回避します。
Docker 公式ドキュメント今回の環境
- Ubuntu Server 20.04 on VMware ESXi
いざ挑戦
まずは事前準備
uidmap 導入
ホスト上に newuidmap と newgidmap のインストールが必要です。
とのことなので、インストールしておきます。
$ sudo apt install -y uidmapこれをインストールしていないと Docker をインストールする際に
# Installing stable version 19.03.12 # Missing system requirements. Please run following commands to # install the requirements and run this installer again. # Alternatively iptables checks can be disabled with SKIP_IPTABLES=1 cat <<EOF | sudo sh -x apt-get install -y uidmap EOFと言われるので入れ忘れないようにしましょう。(体験談)
UID/GID 確認
/etc/subuid と /etc/subgid はユーザに対して、少なくともサブオーディネイト UID/GID を 65,536 含むべきです。
とのことなので確認しておきましょう。
$ grep ^$(whoami): /etc/subuid dev:100000:65536 $ grep ^$(whoami): /etc/subgid dev:100000:65536
65536
が両方に含まれていれば OK です。インストール
ワンライナーで導入できるのは通常の Docker と同じです。
$ curl -fsSL get.docker.com/rootless | sh # Installing stable version 19.03.12 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 57.9M 100 57.9M 0 0 18.0M 0 0:00:03 0:00:03 --:--:-- 18.0M % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 18.3M 100 18.3M 0 0 6245k 0 0:00:03 0:00:03 --:--:-- 6245k # starting systemd service ● docker.service - Docker Application Container Engine (Rootless) Loaded: loaded (/home/dev/.config/systemd/user/docker.service; disabled; vendor preset: enabled) Active: active (running) since Sat 2020-07-25 08:07:23 UTC; 21ms ago Docs: https://docs.docker.com Main PID: 45635 (rootlesskit) CGroup: /user.slice/user-1000.slice/user@1000.service/docker.service tq45635 rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2 tq45647 /proc/self/exe --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2 mq45656 newgidmap 45647 0 1000 1 1 100000 65536 Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + which slirp4netns Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ] Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + which vpnkit Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + net=vpnkit Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ] Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + mtu=1500 Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ] Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + _DOCKERD_ROOTLESS_CHILD=1 Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + export _DOCKERD_ROOTLESS_CHILD Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + exec rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2 Client: Docker Engine - Community Version: 19.03.12 API version: 1.40 Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:42:53 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.12 API version: 1.40 (minimum version 1.12) Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:49:35 2020 OS/Arch: linux/amd64 Experimental: true containerd: Version: v1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 # Docker binaries are installed in /home/dev/bin # WARN: dockerd is not in your current PATH or pointing to /home/dev/bin/dockerd # Make sure the following environment variables are set (or add them to ~/.bashrc): export PATH=/home/dev/bin:$PATH export DOCKER_HOST=unix:///run/user/1000/docker.sock # # To control docker service run: # systemctl --user (start|stop|restart) docker #これでインストールが完了しました。
ですがこのままではdocker
コマンドは使えません。
※パスが通っている場所にインストールしたわけではないため
docker
コマンドを使えるようにするために環境変数に追加します。$ export PATH=/home/dev/bin:$PATH $ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock実際に確認してみましょう。
$ docker info Client: Debug Mode: false Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 1 Server Version: 19.03.12 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: false Logging Driver: json-file Cgroup Driver: none Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd init version: fec3683 Security Options: seccomp Profile: default rootless Kernel Version: 5.4.0-42-generic Operating System: Ubuntu 20.04.1 LTS OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 7.774GiB Name: docker ID: NURI:7LP5:IHUJ:VSSV:6E5W:VMLS:4D52:X5EJ:CB24:CDJ2:OMAO:LMWB Docker Root Dir: /home/dev/.local/share/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: true Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false Product License: Community Engine
docker
コマンドが使えていることと、Security Options
にrootless
が含まれている点が確認できました。使ってみる
とりあえず
Nginx
を動かしてみましょう。$ docker run -dP --name nginx nginx 11cd14bb3bf8d4b99aa46be825bfd7f51143bc578e68ef265f3add1baa0b19ed $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 11cd14bb3bf8 nginx "/docker-entrypoint.…" 19 seconds ago Up 18 seconds 0.0.0.0:32768->80/tcp nginx $ curl -s localhost:32768 | head -n 5 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>ポートフォワードもしっかり動いていることが確認できました。
$ ps -aux | grep docker dev 1519 0.0 0.0 112232 6856 ? Ssl 10:18 0:00 rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2 dev 1528 7.4 0.1 112872 12060 ? Sl 10:18 0:05 /proc/self/exe --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2 dev 1562 20.5 0.8 1638352 67892 ? Sl 10:18 0:14 dockerd --experimental --storage-driver=overlay2 dev 1583 1.1 0.2 1241920 23784 ? Ssl 10:18 0:00 containerd --config /run/user/1000/docker/containerd/containerd.toml --log-level info dev 1875 0.0 0.0 106976 4780 ? Sl 10:19 0:00 /home/dev/bin/rootlesskit-docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32768 -container-ip 172.17.0.2 -container-port 80 dev 1880 0.0 0.0 103372 2364 ? Sl 10:19 0:00 docker-proxy -container-ip 172.17.0.2 -container-port 80 -host-ip 127.0.0.1 -host-port 32768 -proto tcp dev 1891 0.0 0.0 108872 4604 ? Sl 10:19 0:00 containerd-shim -namespace moby -workdir /home/dev/.local/share/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/2f657a2a65b754ff9bd59254f1cd36b745c3f2679aa795c474e6ba29ead4e560 -address /run/user/1000/docker/containerd/containerd.sock -containerd-binary /home/dev/bin/containerd -runtime-root /run/user/1000/docker/runtime-runc dev 1976 0.0 0.0 5192 740 pts/0 S+ 10:20 0:00 grep --color=auto dockerまた、
root
ユーザーではなくdev
ユーザーで実行していることも確認できました。
- 投稿日:2020-07-25T17:33:27+09:00
Docker逆引きメモ
必要に迫られたDockerの逆引きメモです。
Postgresコンテナでlocaleにja_JP.utf8を設定
手順としてはDockerFile作成、imageのビルドを行う。
Visual Studio CodeのDocker Pluginを使用すると楽。環境
- Windows10 Pro 1909
- Docker 19.03.8
Docker file
FROM postgres:9.6.11 RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.utf8 ENV LANG ja_JP.utf8Build
docker build --pull --rm -f "postgres.9.6.11_ja.dockerfile" -t postgres:9.6.11_ja "."参考
- 投稿日:2020-07-25T16:59:24+09:00
MacでDockerコンテナ上にRedmineを構築する
やろうとした理由
Redmineに対する知識が足りないなーと思ったから。
業務で使っているけれどいつも使う側なので、提供する側のことも覚えておかないとこれから困りそう。MacでDockerコンテナ上にRedmineを構築するよ
本当は、自分のサーバに立てたかったんだけど・・・断念。
他の人も使えるならEC2上に立てて提供するとか考えたんだけど、現状私しかいないし、私もそんなにガッツリ使い込むようなこともなさそうなので。
簡単な実験と動作確認であれば、自分のMacにインストールすれば良いかな、と。本当にMacにRedmineを直接入れようとしたけれど、Dockerでいいんじゃないか?ついでにdockerも勉強しなきゃ、ということでDockerを使うことにしました。
Dockerをインストールしておくこと
MacにはDocker Desktopをインストールしておきました。
この構築時点の状態は次の通り。DockerでRedmineを立ち上げる・・・前の事前確認
1. Macのバージョンを確認しておく
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.5 BuildVersion: 19F1012. Dockerのバージョンを確認しておく
$ docker --version Docker version 19.03.8, build afacb8b3. Dockerイメージを確認しておく
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hybridcloudibm/wexdg latest b482197b4310 2 years ago 5.83GB4. 起動中のDockerコンテナを確認しておく
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c522c16cdb88 hybridcloudibm/wexdg "/opt/ibm/wex/sbin/e…" 22 months ago Exited (255) 20 months ago 8000/tcp, 0.0.0.0:443->443/tcp, 9080/tcp wex-d-g5. docker-compose.ymlファイルを作成しておく
docker-composeするために必要なので、用意しておきましょう。
docker-compose.ymlversion: '3.8' services: redmine: container_name: redmine image: redmine restart: always ports: - 3000:3000 volumes: - ./Redmine/plugins:/usr/src/redmine/plugins - ./Redmine/themes:/usr/src/redmine/public/themes environment: REDMINE_DB_MYSQL: redmine-db REDMINE_DB_PASSWORD: redmine redmine-db: image: mariadb container_name: redmine-db restart: always environment: MYSQL_ROOT_PASSWORD: redmine MYSQL_DATABASE: redmine volumes: - ./db:/var/lib/mysql command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ciDockerでRedmineを立ち上げる(docker-compose)
1. docker-composeコマンドを実行する
一度、docker-compose.ymlの書き方がまずくて失敗しました。
$ docker-compose up -d Pulling redmine (redmine:)... latest: Pulling from library/redmine 6ec8c9369e08: Pull complete c307964a7468: Pull complete fd2d286493eb: Pull complete cf773e09df35: Pull complete f41f225850f3: Pull complete f5fa7c9620c6: Pull complete d8bca7298389: Pull complete 80af857119c9: Pull complete 4c1c6ad5d293: Pull complete 11ed9a8222ad: Pull complete d89a2de0559e: Pull complete fa1eb2d25805: Pull complete 25bd4bebd31d: Pull complete Digest: sha256:d2b5a7acbf2ecbc7f5f7078cd3479237553f921ef636e8112bb7430b32ad0222 Status: Downloaded newer image for redmine:latest Pulling redmine-db (mariadb:)... latest: Pulling from library/mariadb 3ff22d22a855: Pull complete e7cb79d19722: Pull complete 323d0d660b6a: Pull complete b7f616834fd0: Pull complete 78ed0160f03e: Pull complete a122e9306ac4: Pull complete 673e89352b19: Pull complete caf1e694359b: Pull complete 04f5e4f6ead3: Pull complete a41772aadb3d: Pull complete c3811aa2fa0a: Pull complete 655ad574d3c7: Pull complete 90ae536d75f0: Pull complete Digest: sha256:812d3a450addcfe416420c72311798f3f3109a11d9677716dc631c429221880c Status: Downloaded newer image for mariadb:latest Creating redmine ... done Creating redmine-db ... done2. dockerイメージを確認する
redmineとmariadbが追加されていることが確認できます。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mariadb latest 8075b7694a2d 15 hours ago 407MB redmine latest 809721a71330 2 days ago 544MB hybridcloudibm/wexdg latest b482197b4310 2 years ago 5.83GB3. 起動中のDockerコンテナを確認する
redmineとmariadbが起動(STATUSでUpになっている)していることが確認できます。
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e9c787057ae4 redmine "/docker-entrypoint.…" 25 seconds ago Up 23 seconds 0.0.0.0:3000->3000/tcp redmine 8619aa4a4c36 mariadb "docker-entrypoint.s…" 25 seconds ago Up 23 seconds 3306/tcp redmine-db c522c16cdb88 hybridcloudibm/wexdg "/opt/ibm/wex/sbin/e…" 22 months ago Exited (255) 20 months ago 8000/tcp, 0.0.0.0:443->443/tcp, 9080/tcp wex-d-g4. ブラウザで起動したRedmineを確認する
http://localhost:3000/ で開くはず。
開かなかったら、ここまでの何かが悪い。これで本来やりたかったことができる・・・!
Redmineへのログインは admin/admin です。
ログインしたらパスワード変更を求められます。やってみた感想
本来やりたかったRedmine以前のDocker周りで苦労しました。
Dockerを全然覚えていないんだな、ということを再認識。
使いこなせると本当に便利だと思うんだけれど・・・コンテナも今や「できて当たり前」なので、ちゃんと勉強しなきゃ。参考にさせていただいた記事など
- 投稿日:2020-07-25T16:05:13+09:00
Kerberos.io Setting @ docker
Kerberos.oiは監視カメラ ソリューションで、設定も単純。Dockerで導入するのも簡単だけど、ドキュメントが少ないのでdocker-compose.yamlを作成してみた時のメモを公開。
kerberos.io
https://www.kerberos.io/準備
- Linux Server:Ubuntu 20.04 LTS [hogehoge.com]
- カメラ1:IP Camera: Axis M2026LE Mk-II. StreamはH264の入力には対応していないのでMJPEGを選択。
RTSP Address: rtsp://username:pass@192.168.1.149/onvif-media/media.amp?profile=profile_1_jpeg&sessiontimeout=60&streamtype=unicast&- カメラ2:USB UVC Camera:中国で買った安いもの。ラズパイならPiCameraでもOK。
/dev/video0UVC Camera Setting
* ディレクトリ作成と認証ファイルのシンボリックリンク
$> mkdir kerberos_usb $> cd kerberos_usb $> touch docker-compose.yaml
docker-compose.yaml
version: '2' services: app_krb: image: kerberos/kerberos devices: - /dev/video0:/dev/video0:mwr environment: - VIRTUAL_HOST - TZ=Asia/Tokyo ports: - 30080:80 - 8889:8889 volumes: - ./kerberosio:/etc/opt/kerberosioアクセスして確認
http://hogehoge.com:3380/USB UVCカメラ設定
LoginしてConfiguration->Machinery->Advanced設定->Capture->USBcamera
IP Camera Setting
ディレクトリ作成と認証ファイルのシンボリックリンク
$> mkdir kerberos_ip $> cd kerberos_ip $> touch docker-compose.yamldocker-compose.yaml
version: '2' services: app_krb: image: kerberos/kerberos environment: - VIRTUAL_HOST - TZ=Asia/Tokyo ports: - 30081:80 - 8888:8889 volumes: - ./kerberosio:/etc/opt/kerberosioアクセスして確認
http://hogehoge.com:3381/IPカメラ設定
LoginしてConfiguration->Machinery->Advanced設定->Capture->IP Camera
ストリーム確認
http://hogehoge.com:8888/mjpeg
- 投稿日:2020-07-25T13:53:29+09:00
Rails アプリケーション作成手順
概要
Dockerを使ってRails開発を始めれるように自分用のメモとして作成しました。
使用するDBはmysqlです。1.アプリケーション用のbuild contextを作成
フォルダの名前:アプリケーション名
build context内:Dockerfile, docker-compose.yml, Gemfile Gemfile.lock
を作成します。2.rails new を実行する
コマンド$docker-compose run web rails new . --force --database=mysql --skip-bundle3.database.ymlを編集する
database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password # docker-compose.ymlのMYSQL_ROOT_PASSWORD host: db # docker-compose.ymlのservice名4.docker buildしてGEMを読み込む
コマンド# コンテナをビルド $ docker-compose build # コンテナを起動 $ docker-compose up -dDBを作成
コマンド$ docker-compose run web rails db:createブラウザでlocalhost:XXXXにアクセスしてサーバ起動を確認する。
- 投稿日:2020-07-25T13:13:35+09:00
docker runでエラーが出る時の対処法(docker: you are not authorized to perform this operation: server returned 401.)
環境 バージョン macOS Catalina 10.15.6 Docker 19.03.8 Macのターミナルから
docker run
コマンドで起動しようとした時に
以下のようなエラーが発生したので、その対処法を備忘録としてまとめます。docker: you are not authorized to perform this operation: server returned 401. See 'docker run --help'.原因
どうやらDockerの「Docker Content Trust(DCT)」という検証機能が影響しているようでした。
これは、イメージが改ざんされていないか等を検証する機能なのですが、イメージに特に問題がないことが
わかっている場合は、以下のコマンドで環境変数を設定して、DCTを無効化します。$ export DOCKER_CONTENT_TRUST=0これで、docker runコマンドが実行できるようになりました。
- 投稿日:2020-07-25T13:11:55+09:00
ローカルのDockerにLAMP環境を構築
はじめに
ローカルのDockerにLAMP環境を構築する方法です。
以下の環境を構築します。
Windows10Proに構築します。
- CentOS7.4.1708
- PHP7.2
- Laravel5.5
- Apache
- MySQL5.7
- phpMyAdmin]
※予め出来ているDockerファイルを利用するため、Dockerファイルの作成方法などを記載するわけではありません。
Docker Desktopのインストール
以下のサイトからDocker Desktopをインストールします。
https://www.docker.com/get-startedDockerファイル群の配置
以下から、ApaLara.zipをDLし、任意の場所に配置します。
https://github.com/shinjinakatamari/LAMP配置フォルダの追加
DockerDeskTopを開き、のsetting>Resources>FILE SHARINGで設定フォルダを追加し、Apply&Restartをクリックする
コマンドの実施
コマンドプロンプトを起動し、以下のコマンドで、配置フォルダに移動する。
cd c:¥・・・以下のコマンドを実行し、Dockerの作成と立ち上げを行う。
docker-compose build docker-compose up -d起動確認
http://localhost/
上記にアクセスすると、Laravelのページが表示される。http://localhost:8080/
上記にアクセスすると、PHPMYAdminのページが表示される。
- 投稿日:2020-07-25T11:46:55+09:00
ISUCON9予選をDockerだけで動かす
isucon/isucon9-qualifyを、ローカル環境にDockerを使って構築します。MySQLやGoはインストールすること無くDockerだけで動かします。アプリケーションにはRubyを利用します。(Rubyもインストールする必要はありません)
完成品は下記です。
https://github.com/s2terminal/isucon9-qualify-docker環境
- ASUS Chromebook Flip C434TA (Core i5モデル)
- ChromeOS Crostini (Linux) Debian 9.11
- Docker 19.03.4
構築手順
まず
git clone
します。$ git clone git@github.com:isucon/isucon9-qualify.git $ cd isucon9-qualify下準備
リポジトリに含まれていない初期画像ファイルのダウンロードが必要なのですが、1.5GBあるので先に落としておきます。
$ wget https://github.com/isucon/isucon9-qualify/releases/download/v2/bench1.zip $ wget https://github.com/isucon/isucon9-qualify/releases/download/v2/initial.zipダウンロードできたら、解凍してそれぞれ所定のディレクトリに移動します。
$ unzip bench1.zip $ unzip initial.zip $ mv v3_initial_data webapp/public/upload $ mv v3_bench1 initial-data/images初期データの準備をします。中ではperlのDockerコンテナを使ってSQLを生成するなどしているようです。
$ cd initial-data $ makeRuby環境準備
Rubyアプリケーションを実行する準備をします。
webapp/ruby
ディレクトリにDockerfileを配置します。webapp/ruby/DockerfileFROM ruby:2.7.1 WORKDIR /app RUN apt-get update \ && apt-get install -y \ mariadb-client \ less COPY ./Gemfile ./ COPY ./Gemfile.lock ./ RUN bundle install CMD /bin/sh -c "while sleep 1000; do :; done"
mariadb-client
は必須です。他にless
だけ入れていますが、追加で欲しい物があれば随時入れておきます。ISUCON用ということは中に入ってなんやかんやしたいと思うので、キャッシュを消したりはせずに置いておきます。
CMD /bin/sh -c "while sleep 1000; do :; done"
で、コンテナが立ち上がりっぱなしになるようにしています。プロジェクトルートに
docker-compose.yml
を配置します。docker-compose.ymlversion: '3' services: ruby: build: ./webapp/ruby volumes: - .:/app ports: - 127.0.0.1:5555:5555 - 127.0.0.1:7000:7000 - 127.0.0.1:8000:8000 environment: - MYSQL_HOST=db - MYSQL_USER=root - MYSQL_PASS=secretMySQL環境準備
データベースの準備をします。DBだけDockerを使ってISUCON9の環境構築した - teru_0x01.logを参考に、
webapp/sql/conf/my.cnf
を作成します。$ mkdir webapp/sql/confwebapp/sql/conf/my.cnf[mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql secure-file-priv= NULL # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 slow_query_log = 1 long_query_time = 5 [client] default-character-set = utf8mb4 # Custom config should go here !includedir /etc/mysql/conf.d/
docker-compose.yml
に下記を追記します。docker-compose.ymldb: image: mysql:5.7 volumes: - ./webapp/sql:/docker-entrypoint-initdb.d - ./webapp/sql/conf:/etc/mysql/conf.d - ./datadir:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=secret - MYSQL_HOST=127.0.0.1 - MYSQL_USER=root - MYSQL_PASS=secret ports: - 127.0.0.1:3306:3306アプリケーションの起動
Rubyコンテナに入って下記実行します。
$ docker-compose exec ruby /bin/bash初回起動時やDBをリセットした時などは、DBの初期化処理を実行します。
# ./webapp/sql/init.shisucon9-qualifyのプロビジョニングファイルのサービス定義ディレクトリを参考に、アプリケーションを起動します。
# cd webapp/ruby && bundle exec rackup --port 8000 --host 0.0.0.0http://localhost:8000/ にアクセスして、ISUCARIが表示されたら成功です。
もし下記のようなエラー画面が表示された場合はRubyのエラーログを確認します。(自分の場合はDBの接続文字列が間違っていました)
git管理する場合は、MySQLのデータマウントに使うディレクトリを
.gitignore
に入れておきます。ついでに私はtmp/
ディレクトリにダウンロード済ファイルを放り込んでいましたので、お好みで。.gitignoredatadir/ tmp/ベンチマーカーのビルド
ベンチマーカーの実行バイナリはリポジトリに含まれておらず、Goでビルドする必要があります。ビルド用のコンテナを準備するために
docker-compose.yml
に追記します。docker-compose.ymlgolang: image: golang:1.14.6 volumes: - .:/app working_dir: /app command: /bin/sh -c "while sleep 1000; do :; done"ベンチマーカーの
Makefile
はプロジェクトルートにありますので、下記コマンドでビルドします。$ docker-compose exec golang make他にもGoに依存している所があるかなと思って
docker-compose.yml
に記述して立ち上げておきましたが、このベンチマーカーのビルドの1回しか使いませんでした。1回$ docker run
するだけで良かったかもしれません。ベンチマーク実行
rackを起動した状態で、Rubyのコンテナ内で
$ ./bin/benchmarker
すればベンチマークを実行できます。しかし今回使った環境(Chromebook C434TA Core i5 Crostini + Docker)では重すぎるのか、スコア記録前の/initialize
へのPOSTでタイムアウトしてしまいスコアが付きませんでした。調べてみると、
init.sh
のSQLを流すのに1分以上かかっているのが原因のようです。$ time ./webapp/sql/init.sh (中略) real 1m2.555s user 0m1.872s sys 0m0.536sISUCON9予選マニュアルには POST /initialize が20秒以内と記載されており、ベンチマーカーの実装も20秒でタイムアウトするようになっているようです。
これは恐らくルール違反なのですが、
init.sh
のSQLを先に手動で流した後、SQL実行をスキップするように修正してからベンチマークを動かすことで、やっとスコアが付きました。webapp/sql/init.shexport LANG="C.UTF-8" cd $CURRENT_DIR -cat 01_schema.sql 02_categories.sql initial.sql | mysql --defaults-file=/dev/null -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER $MYSQL_DBNAME +# cat 01_schema.sql 02_categories.sql initial.sql | mysql --defaults-file=/dev/null -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER $MYSQL_DBNAME
# ./bin/benchmarker (中略) {"pass":true,"score":810,"campaign":0,"language":"ruby","messages":[]}スコアは810点でした。Macbook Proだと3,000ぐらい出るようですが、Chromebook上のLinux仮想環境と、その上にDockerを載せているという二重のオーバーヘッドがパフォーマンスを下げているのでしょうか。
参考
完成品は下記です。
https://github.com/s2terminal/isucon9-qualify-docker/pull/1
- 投稿日:2020-07-25T07:48:44+09:00
Docker上にGrafanaとInfluxDBを構築する
事前準備
事前にWSL2とかDocker Desktopとかのインストールを終わらせておくこと
- Windows10でWSL2を使う
- Docker Desktop をWSL2で利用する。環境
Windows10
WSL2
Docker Desktop
Grafana 7.1.1コンテナを作る
docker-compose.yml
version: "2" services: influxdb: image: influxdb container_name: local-influxdb #grafanaからアクセスするための名前 volumes: - /home/xxxx/docker/grafana/influxdb:/var/lib/influxdb ports: - 8086:8086 grafana: image: grafana/grafana:7.1.1 ports: - 8085:3000 #grafanaのポート user: "472" volumes: - /home/xxxx/docker/grafana/grafana:/var/lib/grafana depends_on: - influxdb environment: - GF_SERVER_ROOT_URL=http://192.168.77.6:8085 - GF_SECURITY_ADMIN_PASSWORD=admin起動
docker-compose up -d
ログを確認
docker-compose logs -f
はい、エラーが出ました。
grafana_1 | You may have issues with file permissions, more information here: http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later権限がないということなので、ホスト上でオーナーを変更
cd /home/xxxx/docker/grafana/ mkdir grafana sudo chown 472:472 grafana改めて起動して、ログを確認。エラーが出てなければ完了です。
Grafanaを表示する
ブラウザでhttp://localhost:8085にアクセスすると、以下の画面が表示されればOKです。
admin/adminでログインできます。さいごに
docker使うとほんと簡単に環境ができますね。
さて次は、中身の設定ですね。
- 投稿日:2020-07-25T07:26:05+09:00
Docker の Volume がよくわからないから調べた
前提
- 本記事執筆時の Docker 最新バージョン: 19.03
- 書いている人は、業務で本格的に docker を使ったりしておらず、個人開発で適当に使っていたが、よくわからず使っている部分もあったので改めて調べてるレベル。
悩み
- データを永続化したい場合に、
-v
オプションや、Dockerfile のVOLUME
や、Compose ファイルのvolumes
を使ったりしていたが、違いをよくわかっていない。それぞれ記法もいくつかあるようだがよくわかっていない。- コンテナ消した時に勝手に破棄される場合もあってよくわからないので、ホスト側のディレクトリをコンテナ内のディレクトリにマッピングするやつを使いがち。ホスト側のディレクトリが見えているので安心しちゃう。
- Data Volume コンテナがいいぞ、と言われたので使っているが、なんでいいのかわかってない。
- とにかくよくわからないまま使っている。
この記事の概要
- 公式ドキュメントに全部書いてあるので詳しくはこちらへ。この記事は理解のポイントだけおさえてあります。
- Docker のストレージにはボリュームとバインドマウントと tmpfs の3種類がある。
--volume
というオプションでボリュームもバインドマウントも指定できるので、オプション名と機能の名前がかぶっててややこしいから混乱する。-v
オプションじゃなく--mount
オプションを使おう。- Data Volume コンテナは、そういう機能があるわけではなくデザインパターン。
- 名前付きボリュームを使おう。
Docker のストレージの考え方
コンテナ内で発生したデータは同じコンテナ内のどこかに書き出されるが、コンテナを破棄すると消えてしまいます。データだけはコンテナが消えても保存しておきたかったり、別コンテナで使いたいというニーズに対して、Docker はコンテナ外にデータ保存領域をつくる機能を提供しています。
具体的には3種類。(厳密にいうと、Windows で名前付きパイプっていうのもある)
- ボリューム
Docker の管理下でストレージ領域を確保する。Linux なら/var/lib/docker/volumes/
以下。
名前付きボリュームと匿名ボリュームがあり、名前付きの場合は Docker ホスト内で名前解決できるのでアクセスしやすい。匿名ボリュームは適当にハッシュ値が振られる。
他のプロセスからはさわれないので安全。基本はこれを使うのがよい。- バインドマウント
ホスト側のディレクトリをコンテナ内のディレクトリと共有する。- tmpfs
メモリ上にストレージ領域を確保する。名前の通り一時的な領域となる。用途としては、機密性の高い情報を一時的にマウントする場合などに使う。
-v
オプションも、VOLUME
やvolumes
で指定するものに関しても、基本的には上記のどれかを扱っています。普通に使う分にはボリュームかバインドマウントになるので、以下はそのふたつをメインに説明します。-v オプション
自分の場合は
-v
オプションでいろいろ指定ができるのが混乱の原因のひとつでした。
上記3種類のストレージが理解できていればなんてことないのですが。
sample/image:latest というイメージを run するとして、以下に記法による違いを列挙します。
- 匿名ボリューム
$ docker container run -v /hoge sample/image:latest
ホスト側には、Linux なら/var/lib/docker/volumes/
以下に領域が確保され、コンテナ内の/hoge
ディレクトリと共有される。識別のためにハッシュ値が振られる。同じネットワークからそのハッシュ値でアクセスできる。- 名前付きボリューム
$ docker container run -v name:/hoge sample/image:latest
匿名ボリュームと同様に、ホスト側には、Linux なら/var/lib/docker/volumes/
以下に領域が確保され、コンテナ内の/hoge
ディレクトリと共有される。name
という名前がついているので、同じネットワーク内からname
というホスト名でアクセスできる。- バインドマウント
$ docker container run -v ${PWD}/data:/hoge sample/image:latest
ホスト側のカレントディレクトリ配下のdata
ディレクトリと、コンテナ側の/hoge
ディレクトリが共有される。--mount オプション
Docker 17.06 から単一のコンテナに対しても
--mount
オプションが使えるようになっており、公式でも-v
の代わりにこちらを使うことが推奨されてます。(Swarm では前から使っていた)
キーバリュー形式で各要素が指定できるので、こちらの方が記法としては明快です。長くなるけど。
こんな感じで指定します。
$ docker container run --mount type=volume, src=name, dst=/hoge sample/image:latest
- type
volume
,bind
,tmpfs
を指定- src
名前付きボリュームであれば、その名前。バインドマウントであればホスト側のディレクトリを指定します。匿名ボリュームであれば省略します。
他にsource
とも書ける。- dst
コンテナ側のディレクトリを指定します。
他にdistination
,target
とも書ける--rm オプションをつけたとき
$ docker container run
する時に、--rm
オプションをつけると、匿名ボリュームの場合はコンテナ停止と同時にボリュームも破棄されます。
名前付きボリュームの場合は--rm
オプションでコンテナが破棄されても破棄されません。ただ名前付きボリュームであっても、マウントされたコンテナがない状態では、
$docker volume prune
などでは破棄されます。Data Volume コンテナは単なるデザインパターン
Volume を調べているとよく出てくる Data Volume コンテナ。
これは Docker の機能としてそういうものがあるのではなく、ボリュームを扱いやすくするためのデザインパターンです。ボリュームに対してコンテナを紐付けておくとなにがうれしいのか、というと、ボリュームへのアクセスが抽象化できるので扱いやすくなったり、うっかり prune で破棄してしまったりしなくて済むということじゃないかと思います。(たぶん)
結局どれ使ったらいいの?
基本的には名前付きボリュームを使いましょう。
Docker 領域下にボリュームができるから安全ですし、名前でアクセスできるので扱いやすいです。
バインドマウントは、ホスト側の環境に依存しますし、ボリュームに比べて機能が制限されています。ホスト側からデータを注入したいときや、開発時に更新したソースコードやビルドを即時反映したい場合などの場合はバインドマウントを使うのがよいです。まとめ
- Docker のストレージにはボリュームとバインドマウントと tmpfs の3種類がある。
- -vオプションじゃなく--mountオプションを使おう。
- 基本は名前付きボリュームを使おう。
参考文献
- 投稿日:2020-07-25T01:53:38+09:00
yamlで保存してあるconda仮想環境をDocker上で構築
Docker上でPython環境を作るときに
pip
やPipenv
なども使うのだが、使うライブラリやパッケージの関係でconda
環境を使えると便利なことがある。
思った通りのconda環境をDocker上で作るための方法の自分用メモ。1. 動機
Pythonの開発やデータ分析などでMinicondaやAnacondaを使うことがある。
(依存ライブラリも割と一緒にインストールしてくれるので自分で入れなくて良いなど環境構築が楽だったり、バイナリ互換性の問題でcondaの特定チャンネルからのインストールを推奨されるパッケージがあったりする)
その際、やっている作業毎にパッケージやバージョンを変えたかったり、環境を後で再現しやすくするなどの目的で基本はconda仮想環境を使うようにしている。
が、Python以外のところから環境設定・構築が必要になることがあったり、仮想環境と言えどもPCの環境を汚して他と干渉したりの問題が起きるなどで、結局Dockerで対応することが多いため。(で、そのDockerへの移植時に結構苦戦したため)yamlファイルを使う理由
詳細は次章として、
- PC上の既存のconda仮想環境を容易にDocker上に移植出来る
- 逆に、Docker上で開発したconda環境を手元のAnacondaやMinicondaですぐに再現出来る
など
2. conda環境の保存と再構築
2-1. yamlファイルからのconda環境生成
conda env create -f environment.ymlを実行すると、
environment.yml
に記載した情報の通りにconda環境が生成される。
例えばenvironment.yml
に対応するものをgit上などで管理しておくと、可搬性や再現性の点で便利。※
environment.yml
の中身は以降の記述を参考
※conda env create
以降のオプションの詳細ははっきり覚えていない。。。発見出来てかつ気が向いたら後で追記。ちなみにconda create
のオプションはこんな感じ。2-2. yamlファイルの生成
対象のconda仮想環境に入って、例えば以下のようにする
conda env export > environment.ymlすると、該当のconda環境でインストールされていた全パッケージとそのバージョン(ビルド情報含む)が
environment.yml
に書き出される。(pip freeze
するような感覚)ちなみに、仮想環境に入らなくとも
conda env export -n <仮想環境名> > environment.ymlのようにして、明示的に書き出す仮想環境名を指定することも出来る。
また、上記の2つは完全にバージョン情報が固定されるが、そこまではせずに最低限の条件だけ指定したい場合がある。
(公式ドキュメント)を参考にして、パッケージと使うチャンネルなどを書いたyamlファイルを自分で作ることが出来る。(以下、適当な例)create_env_sample.ymlname: hoge channels: - conda-forge - default dependencies: - python==3.7.* - pandas<1.0 - flask - pip - pip: - pynvim
- 依存ライブラリなどは(conflictが起きなければ)自動でインストールされる。
- pipでインストールされるものも書ける。(
pip:
の下のところ)
- 先にcondaでのインストールが実行され、最後にpipでのインストールが実行される
- condaでインストールするパッケージ内で明示的にpipをインストールしておくと無難かもしれない
- 「conda仮想環境のものでないpipを使う可能性がある」的な趣旨のwarningが出る
なお、上記の例のyamlファイルだと、
# condaでパッケージをインストール conda create -n hoge python=3.7 pandas\<1.0 flask pip -c conda-forge # 作った仮想環境に入る conda activate hoge # 最後にpipで必要なパッケージをインストール python -m pip install pynvimみたいな感じで環境構築するのと大体同じ。(※厳密に本当に同じかまでは未検証)
3. Docker上でconda仮想環境を作る
(方針)
- 前章を踏まえて用意してあるyamlファイルをDockerイメージ内に
COPY
などしておく- yamlファイルからの環境作成はMinicondaを利用して行う
- Miniconda自体のインストールは公式などを参照
- continiuum公式のDockerfileなども参考になる
- 上記のMinicondaはyamlファイルから仮想環境を作ること「のみ」に使い、作り終わったら元のMinicondaはキャッシュ毎全部消す(←容量の無駄なので)
- 代わりにyamlから作られた仮想環境の方を
base
にする- (もっと良いやり方があるかもしれない)
Dockerfile作成例(抜粋)
ディレクトリ構成:
tree . # . # ├── Dockerfile # └── environment.ymlのような感じ。
docker build --tag=hoge .または
# Dockerfile内のARG部分を制御する場合 docker build \ --tag=hoge \ --build-arg VAL1=FOO \ --build-arg VAL2=BAR \ .のようにすると、ビルドが通れば
hoge
というイメージが出来るDockerfileARG BASE_IMAGE=ubuntu:latest FROM ${BASE_IMAGE} # system update & package install RUN apt-get clean && \ apt-get -y update && \ apt-get install -y --no-install-recommends \ unzip bzip2 \ openssl libssl-dev \ curl wget \ ca-certificates \ locales \ bash \ sudo \ git \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # ローカルuser作成 ARG USER_NAME=user ARG USER_UID=1000 ARG PASSWD=password RUN useradd -m -s /bin/bash -u ${USER_UID} ${USER_NAME} && \ gpasswd -a ${USER_NAME} sudo && \ echo "${USER_NAME}:${PASSWD}" | chpasswd && \ echo "${USER_NAME} ALL=(ALL) ALL" >> /etc/sudoers && \ chmod g+w /etc/passwd # conda用準備 ENV CONDA_DIR=/opt/conda \ CONDA_TMP_DIR=/tmp/conda \ HOME=/home/$USER_NAME \ SHELL=/bin/bash RUN mkdir -p $CONDA_DIR && \ mkdir -p $CONDA_TMP_DIR && \ chown $USER_NAME:$USER_UID $CONDA_DIR && \ chown $USER_NAME:$USER_UID $CONDA_TMP_DIR # yamlファイルの取り込み ARG CONDA_YAML="./environment.yml" COPY $CONDA_YAML /tmp/conda_packages.yml USER ${USER_NAME} WORKDIR $HOME # miniconda ARG MINICONDA_VERSION=py37_4.8.3-Linux-x86_64 ARG MINICONDA_MD5=751786b92c00b1aeae3f017b781018df ENV PATH=${CONDA_DIR}/bin:$PATH RUN cd /tmp && \ wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-${MINICONDA_VERSION}.sh && \ echo "${MINICONDA_MD5} *Miniconda3-${MINICONDA_VERSION}.sh" | md5sum -c - && \ /bin/bash Miniconda3-${MINICONDA_VERSION}.sh -f -b -p $CONDA_TMP_DIR && \ rm Miniconda3-${MINICONDA_VERSION}.sh && \ $CONDA_TMP_DIR/bin/conda env create -f /tmp/conda_packages.yml -p $CONDA_DIR && \ rm -rf $HOME/.cache/* && \ rm -rf $CONDA_TMP_DIR/* # (以下省略)
- はじめにMinicondaは
/tmp/conda/
下にインストールする
- 先述の通り、
conda env create
をするためだけに使うので、後で/tmp/conda/
下をまるっと消す- インストール先は
-p
オプションで指定している- 所望のconda環境は
/opt/conda/
下にインストールされ、ここにPATH
を通すことで作成ユーザーにとってのデフォルトPython環境にしている
- conda環境を
/opt/conda/
にするために、-p
や--prefix
オプションでインストール先を指定- イメージサイズが肥大化しないように、Minicondaのダウンロード・インストールから不要なファイル・キャッシュの削除まで1つの
RUN
の中で全てをやり切る必要(補足)
- 使っているMinicondaは執筆時点(2020-07-24)での最新版なので、ここなどを参考に適宜アップデートする
- ユーザー作成を行っているが別に必須ではないので、そこを省けばもっとすっきりするはず
- yamlファイルにおける
prefix:
部分があればそれはインストール場所を示すが、conda env create
の-p
ないし--prefix
オプションでの指定が優先される様子- yamlファイルに書くインストールパッケージの中に
conda
を書いておくと、/opt/conda/
にインストールされる仮想環境が新しいbase
環境になる
- コンテナ使用中に追加で入れたいパッケージが出てきたときにその場で
conda install ***
を実行出来たり、その後conda env export -n base | tee environment.yml
などと叩いてインストールパッケージの再確認や新しいyamlファイルの生成が出来る(更に細かい補足)
たまに
conda env export
で生成したyamlファイルをそのままconda env create
に渡せないときがある(あった)ので、その例と対処。
pip
でgraphviz
をインストールさせたものをconda env export
してyamlを生成すると、python-graphviz
の名前になっている- しかし、
pip install python-graphviz
はエラーになるため、したがってこのyamlファイルをそのまま使うとインストールエラーになってしまう- そこで、例えば以下の部分を挿入してyamlファイルを少しだけ書き換えるなどした
RUN sed -i -e 's/python-graphviz/graphviz/' /tmp/conda_packages.yml
sed
でyamlファイル内のpython-graphviz
をgraphviz
に置換している参考
conda環境の保存・構築:
https://qiita.com/nshinya/items/cb1cffabc3305c907bc5
https://qiita.com/yubessy/items/2dd43551aa8308dc7ecaDocker上でのconda環境の構築
https://hub.docker.com/r/continuumio/miniconda/dockerfile
https://github.com/jupyter/docker-stacks/tree/master (←リポジトリ内の各Dockerfileを参照)