20190413のdockerに関する記事は15件です。

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (プロキシ版)

概要

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)を会社等のプロキシ環境で使う際の設定になります。

環境

Ubuntu 18.04

目指す環境

  • python==3.5
  • tensorflow==1.12.0
  • docker内でグラフプロット等のGUI使用可能
  • プロキシ環境で動作するコンテナ

下準備

1. dockerのインストール

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の1を参照

2. ホスト側のGUI表示用設定

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の2を参照

3. NVIDIAドライバーとnvidia-docker2のインストール(GPU使用の場合)

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の3を参照

4. dockerのプロキシ設定とsudoなし設定

docker pull等を実行できるようにdockerのプロキシ設定を行います。
あとsudoも使わなくていいように設定しておきます。

参考記事 : Ubuntu Docker インストールとproxyとsudo無し実行

5. DNSの設定

Ubuntuの場合、dockerコンテナのDNS設定はホスト側のDNS設定を引き継ぎます。
具体的にはホストの「/etc/resolve.conf」がコンテナ内にコピーされます。
この際にGUIの設定画面等で設定したホスト側のDNS設定やDHCPから配布された設定が「/etc/resolve.conf」に反映されていない場合があります。
以下のページを参考に、nameserverが自分自身を指定している場合(127.0.0.1など)の場合は設定を変更して下さい。

参考記事 : Ubuntu 16.10: /etc/resolv.confのnameserver 127.0.0.1を防ぐ

dockerの設定

6. Dockerfile

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)と比べて②環境変数設定, ③apt.confの作成 を追加しています。これでコンテナ内のプロキシ環境変数とaptのプロキシを設定しています。
使用する際は「PROXY_ID」, 「PROXY_PASS」, 「PROXY_HOST」, 「PROXY_PORT」のoooを自分のプロキシの「認証ID」, 「認証パスワード」, 「サーバー名」, 「ポート番号」に変更します。

Dockerfile
# GPUの場合
#FROM tensorflow/tensorflow:1.12.0-gpu-py3
# ①CPUの場合
FROM tensorflow/tensorflow:1.12.0-py3
COPY into_container/requirements.txt /root/

# ②環境変数設定
ENV PROXY_ID ooo
ENV PROXY_PASS ooo
ENV PROXY_HOST ooo
ENV PROXY_PORT ooo
ENV PROXY_SERVER http://"$PROXY_ID":"$PROXY_PASS"@"PROXY_HOST":"PROXY_PORT"
ENV http_proxy "$PROXY_SERVER"
ENV https_proxy "$PROXY_SERVER"
ENV ftp_proxy "$PROXY_SERVER"
ENV HTTP_PROXY "$PROXY_SERVER"
ENV HTTPS_PROXY "$PROXY_SERVER"
ENV FTP_PROXY "$PROXY_SERVER"

# ③apt.confの作成
RUN echo "Acquire::ftp::proxy \"""$PROXY_SERVER""\";" > /etc/apt/apt.conf \
 && echo "Acquire::fttp::proxy \"""$PROXY_SERVER""\";" >> /etc/apt/apt.conf \
 && echo "Acquire::fttps::proxy \"""$PROXY_SERVER""\";" >> /etc/apt/apt.conf

# ④パッケージインストール
RUN add-apt-repository -y ppa:jonathonf/vim \
 && apt-get update \
 && apt-get install -y git vim xterm sudo python3-tk \
 && pip3 install --upgrade pip \
 && pip3 install -r /root/requirements.txt

# ⑤ユーザーの切り替え
RUN groupadd -g 1000 developer && \
    useradd  -u 1000 -g 1000 --groups sudo --create-home --shell /bin/bash developer && \
    echo 'developer:P@ssw0rd' | chpasswd
USER developer
WORKDIR /home/developer

7. ビルド

普通にビルドすればOKです。

build.sh
docker build -t baby-steps-env .

8. コンテナ起動

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の5を参照

9. 実行

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の6を参照

7. 動作確認

コンテナ内のbashコンソールで

書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の7を参照

8. Gitリポジトリ

Gitに今回紹介したソースをあげていますのでよければご利用ください。
Ubuntu用 : kinziro/baby-steps-ubuntu-env_on_docker_in_proxy

参考にさせて頂いたサイト

Ubuntu Docker インストールとproxyとsudo無し実行
Ubuntu 16.10: /etc/resolv.confのnameserver 127.0.0.1を防ぐ

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

Windows10で機械学習用に Jupyter Lab 環境を、docker-composeで立ち上げ

Windows10で機械学習用に Jupyter Lab 環境を、docker-composeを使って立ち上げた時のメモ
※ Docker Desktopは入っている前提にしています
※ Windows10と書いていますが Docker をインストールしていれば、volumesを少し修正するだけでLinuxやMac環境でも動くはずです。

jupyter/datascience-notebook

のDockerイメージにはPython、Julia、Rのライブラリが入っています


機械学習用にJupyter Labの立ち上げ

docker-compose.yml

version: '3'
services:
  jupyter:
    image: jupyter/datascience-notebook:latest
    container_name: jupyterlab
    environment:
      TZ: "Asia/Tokyo"
      JUPYTER_ENABLE_LAB: "yes"
    ports:
      - "8888:8888"
    volumes:
      - Z:\docker\jupyter\data/:/home/jovyan/

コマンドプロンプトを立ち上げ

docker-compose up

を実行

ブラウザで
http://localhost:8888
にアクセスし、コマンドプロンプトのログに出ていたtoken=の文字列を

Password or token:

欄に入力しLog inボタン押下

Jupyter Labが立ち上がります

参考

https://jupyter-docker-stacks.readthedocs.io/en/latest/

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

Run Swift on Docker's Linux

References

Step

Docker side

1. Install Docker

$ brew cask install docker

2. Get Ubuntu image

$ docker pull ubuntu

3. Create Container of Ubuntu

$ docker run --privileged -it ubuntu /bin/bash

4. Start Container

$ docker start <ID>

5. Attach container

$ docker attach <ID>

Ubuntu side

1. Update packages

# apt update

2. Install packages that dependent Swift

# apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev systemtap-sdt-dev tzdata rsync

3. Download Swift

# cd /opt/
# apt-get install wget
# wget https://swift.org/builds/swift-4.2-release/ubuntu1804/swift-4.2-RELEASE/swift-4.2-RELEASE-ubuntu18.04.tar.gz

4. Unzip

# tar xvfz swift-4.2-RELEASE-ubuntu18.04.tar.gz
# mv swift-4.2-RELEASE-ubuntu18.04 swift

5. Set path

# export PATH=/opt/swift/usr/bin:"${PATH}"

6. Test

# swift -version
Swift version 4.2 (swift-4.2-RELEASE)
Target: x86_64-unknown-linux-gnu

Memo

Copy host's file to Container

$ docker cp file.cnf <ID>:/etc/file.cnf
$ docker cp dir <ID>:/etc/dir
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerコンテナ上で利用しているLet's Encryptを自動更新する

4月から転職しまして、自社設備の右も左もわからない状態で
「Let's Encryptがそろそろ更新だからやっといて〜」
とのタスクをいただいたのでついでに自動化をば。

dockerでアプリを実装していますが、マウントしているのは証明書だけだったのでホストのcronで回してます。

前提情報 

  • ホスト
    • Amazon Linux
  • コンテナ

    • nginx
  • 証明書保存先

$ ls -al foo/var/certs/
合計 28
drwxrwxr-x  2 ec2-user ec2-user 4096  3月  8 03:57 .
drwxrwxr-x 16 ec2-user ec2-user 4096  4月  8 02:32 ..
-rw-r--r--  1 root     root      692  1月 22 09:15 README
-rw-rw-r--  1 ec2-user ec2-user 1927  3月 26 00:47 cert.pem
-rw-r--r--  1 root     root     1647  1月 22 09:15 chain.pem
-rw-rw-r--  1 ec2-user ec2-user 3574  3月 26 00:47 fullchain.pem
-rw-rw-r--  1 ec2-user ec2-user 1704  3月 26 00:47 privkey.pem

1. どこでLet's Encryptが使われてるか確認

そうです、探すとこからです。

  • とりあえずpstree
$ pstree
略
    ├─dockerd─┬─docker-containe─┬─docker-containe─┬─mysqld───28*[{mysqld}]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─mysql
     │         │                 │                 ├─php-fpm───3*[php-fpm───3*[{php-fpm}]]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─nginx───nginx
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─redis-server───2*[{redis-server}]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─celery───3*[celery]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─postgres───10*[postgres]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 ├─docker-containe─┬─gunicorn───4*[gunicorn]
     │         │                 │                 └─9*[{docker-containe}]
     │         │                 └─19*[{docker-containe}]
     │         ├─docker-proxy───7*[{docker-proxy}]
     │         ├─2*[docker-proxy───5*[{docker-proxy}]]
     │         ├─docker-proxy───6*[{docker-proxy}]
     │         └─21*[{dockerd}]

あ、dockerなんですね。

  • docker-compose情報
$ cat docker-compose.yml
version: '2'
services:
  app:
    build: ./foo/app
    volumes:
      - ./:/var/www
    links:
      - mysql
  web:
    build: ./bar/web
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www
      - ./certs/:/etc/pki/certs
    links:
      - app
  mysql:
    build: ./nyaa/mysql
    ports:
      - "3306:3306"
ry

とりあえず./bar/web/以下のwebコンテナのみ証明書を使用していると判断

$ ls -al ./bar/web/
合計 20
drwxrwxr-x 2 ec2-user ec2-user 4096  3月 14 07:57 .
drwxrwxr-x 5 ec2-user ec2-user 4096  1月 22 08:58 ..
-rw-rw-r-- 1 ec2-user ec2-user  298  1月 22 08:58 Dockerfile
-rw-rw-r-- 1 ec2-user ec2-user  671  1月 22 08:58 nginx.conf
-rw-rw-r-- 1 ec2-user ec2-user  650  3月 14 07:57 vhost.conf
vhost.conf
ry
    ssl on;
    server_name your_domain.jp;
    ssl_certificate /etc/pki/certs/fullchain.pem;
    ssl_certificate_key /etc/pki/certs/privkey.pem;
ry

webコンテナのnginxで使用していることが判明  
(このタイミングで確認しましたがやはり使用しているのはnginxだけでした。)

2. 更新作業

  1. 証明書の更新
  2. dockerコンテナ内nginxのreload

上記手順を自動化します。

証明書の更新

とりあえず更新してみる。

  • 設定ファイル
$ cat /etc/letsencrypt/renewal/your.domain.conf
# renew_before_expiry = 30 days
version = 0.33.1
archive_dir = /etc/letsencrypt/archive/your.domain.jp
cert = /etc/letsencrypt/live/your.domain.jp/cert.pem
privkey = /etc/letsencrypt/live/your.domain.jp/privkey.pem
chain = /etc/letsencrypt/live/your.domain.jp/chain.pem
fullchain = /etc/letsencrypt/live/your.domain.jp/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = xxxxxx
account = your_account_key
server = https://acme-v02.api.letsencrypt.org/directory
[[webroot_map]]
your.domain.jp = /foo/bar/directory
  • 更新を実行
$ sudo /usr/bin/certbot-auto renew
Upgrading certbot-auto 0.30.0 to 0.33.1...
Replacing certbot-auto...
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/your.domain.jp.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator xxxxxx, Installer None
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for your.domain.jp
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/your.domain.jp/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/your.domain.jp/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  • 確認
$ sudo ls -al /etc/letsencrypt/live/your.domain.jp
合計 12
drwxr-xr-x 2 root root 4096  4月  8 03:31 .
drwx------ 3 root root 4096  1月 22 09:12 ..
-rw-r--r-- 1 root root  692  1月 22 09:12 README
lrwxrwxrwx 1 root root   45  4月  8 03:31 cert.pem -> ../../archive/your.domain.jp/cert2.pem
lrwxrwxrwx 1 root root   46  4月  8 03:31 chain.pem -> ../../archive/your.domain.jp/chain2.pem
lrwxrwxrwx 1 root root   50  4月  8 03:31 fullchain.pem -> ../../archive/your.domain.jp/fullchain2.pem
lrwxrwxrwx 1 root root   48  4月  8 03:31 privkey.pem -> ../../archive/your.domain.jp/privkey2.pem

3. 自動化と反映

証明書はちゃんと更新できることが判明したので、自動化してdockerコンテナに反映させます。

更新スクリプトを作成

現在dockerにマウントさせている証明書は上記証明書のコピーとなっている。
自動更新に対応させるため、上記シンボリックリンク先の証明書をvolumeディレクトリにコピーする必要がある。

/usr/local/libexec/lets_encrypt_renew.sh
#!/bin/sh

# 証明書の更新
/usr/bin/certbot-auto renew

# 証明書のコピー(docker_mountは上記docker-compose.ymlのvolumeマウント先です)
cp /etc/letsencrypt/live/your.domain.jp/cert.pem docker_mount/certs/
cp /etc/letsencrypt/live/your.domain.jp/chain.pem docker_mount/certs/
cp /etc/letsencrypt/live/your.domain.jp/fullchain.pem docker_mount/certs/
cp /etc/letsencrypt/live/your.domain.jp/privkey.pem docker_mount/certs/

# nginxのリロード
docker exec -i container_name service nginx reload

timezone設定

cron実行してテストしようとしたらtimezone設定されていなかった。(まじか)
時刻合わせを実施する(設定済みの方は飛ばしてください)

$ sudo cp -a /etc/localtime ~/org/
$ sudo ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

$ sudo cp -a /etc/sysconfig/clock ~/org/
$ sudo vi /etc/sysconfig/clock

$ diff -u ~/org/clock /etc/sysconfig/clock
--- /home/your_user/org/clock   2018-11-17 08:07:41.583229222 +0900
+++ /etc/sysconfig/clock    2019-04-08 14:06:53.465544040 +0900
@@ -1,2 +1,2 @@
-ZONE="UTC"
+ZONE="Asia/Tokyo"
 UTC=true
  • 確認
$ date
2019年  4月  8日 月曜日 14:09:02 JST (あってる。)

cron記載

  • /etc/cron.d/lets_encrypt
30 9 * * 1 root sh /usr/local/libexec/lets_encrypt_renew.sh > /dev/null 2>&1

毎週月曜9:30にスクリプト実行し、デフォルトなので有効期限が30日未満の場合に更新します。
ついでに次回更新時の確認のためにslackでリマインドしました。

cronの時間変えて検証

ちゃんと動作することを確認してください。(cronを実際に動かさないと、パーミッションと環境変数でエラーとかあるあるですよね。)

完了

スクリーンショット 2019-04-13 19.42.41.png

やったぜ。

どのサーバでなにやってるかわからない中、取り急ぎ感が満載ですが無事docker上で使用しているLet's Encryptを更新自動化できました。
これからもいろいろ整備していきます。

ホストがオートスケールだったりマネージドでホストがなかったりするとcronじゃ難しいですが、とりあえず基本としてメモまで。

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

#docker で #ruby に色々と gem を入れたイメージやコンテナを作成するごく簡単な Dockerfile の例

Dockerfile

FROM ruby

RUN gem install reverse_markdown redcarpet

exe

$ docker build . -t ruby-gems
$ docker run -it ruby-gems /bin/bash
root@dd130726b871:/# echo "<h1>Hello</h1>" | reverse_markdown
# Hello
root@dd130726b871:/# echo "<h1>Hello</h1>" | reverse_markdown | redcarpet
<h1>Hello</h1>

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1235

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

WebStormとDockerでコンテナ内に依存ライブラリを閉じ込めてReactの開発環境を作成

ローカル環境に色々入れずに開発環境をDocker上で構築したいけど、コーディングはIDEを使いたいので自分が辿り着いた手順をまとめました。
似たようなことをすればIntelliJ, PyCharm, GoLand, RubyMine, PhpStormでもできそう。

前提

  • WebStorm(or IntelliJ)をインストールしている
  • MacでDocker for Macをインストールしている

WebStormで新規Project作成

[File] -> [New] -> [Project]
image.png

[Empty Project]を選択し、Locationにプロジェクト名を設定して[CREATE]

Setting Value Remark
Location: {PROJECT PATH} PATHの末尾がプロジェクト名

image.png

空のプロジェクトが作成される
image.png

Dockerの設定

コマンドラインかWebStormのGUIのどちらかで設定すれば良い

Dockerfileを利用してコマンドラインで設定する場合

Terminalで以下を実行したあと、Ctrl + p->Ctrl + qで接続したコンテナから抜ける

[LOCAL]$ docker run \
-it \
-p 13000:3000 \
-v {PROJECT PATH}:/app \
--name {CONTAINER NAME} \
-w /app \
node:lts-alpine
Setting Value Remarks
-p 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする。何個も起動させる場合、HOST側のportは重ならないように変えること。
-v {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリと先ほどLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる。
--name {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
-w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

WebStormのDockerプラグインで設定する場合

[WebStorm] -> [Preferences...] で [Build, Execution, Deployment]にあるDockerの設定画面を選択し、+ボタンで新規作成
image.png
image.png

Docker for Macを利用しているので、これを選択し適当に名前をつけて[OK]を選択
image.png

(今回は画面の左下に)Dockerのタブが現れたので(Connect)を押すと、ConnectedとなりContainersImagesというのが表示される
image.png
image.png

Imagesを選択してPull Image
image.png

今回はnode:lts-alpineを利用

Setting Value Remarks
Registry: registry.hub.docker.com デフォルトの設定
Repository: node
Tag: lts-alpine ここは好きなのを選んで良い。今回は軽量と聞くalpineのlts版にした

image.png

Imagesに選択したDockerのimageが表示される
image.png

このimageからコンテナ作成のため+->Create..
image.png
image.png

コンテナ起動の設定を以下のようにしてRUN

Setting Value Remarks
Container name: {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
Bind ports: 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする
Bind mounts: {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリとLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる
Run options: -w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

image.png

Deploy logにコンテナ作成が成功されたログが表示されればOK
image.png

TerminalからDockerコンテナに接続してプロジェクト作成

# コンテナの起動確認
[LOCAL]$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
febece633a44        aa57b0242b33        "node"              About a minute ago   Up About a minute   0.0.0.0:13000->3000/tcp   node-docker

# コンテナへ接続
[LOCAL]$ docker exec -it node-docker /bin/sh
/app # 

ここからdocker上での実行コマンド
コンテナシェルのPS1部分/app #[DOCKER]$に読みかえてる
https://facebook.github.io/create-react-app/docs/adding-typescript を参考にtypescriptのReactプロジェクトを作成

# nodeのversion確認
[DOCKER]$ node --version
v10.15.3

# /appディレクトリにプロジェクト作成
[DOCKER]$ npx create-react-app /app --typescript
npx: installed 63 in 3.522s

Creating a new React app in /app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

yarn add v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "linux" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.4: The platform "linux" is incompatible with this module.
info "fsevents@1.2.4" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 13 new dependencies.
info Direct dependencies
├─ @types/jest@24.0.11
├─ @types/node@11.13.4
~ 省略 ~

Your tsconfig.json has been populated with default values.


Success! Created app at /app
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd /app
  yarn start

Happy hacking!

Dockerコンテナの/appディレクトリに作成されたプロジェクトがWebStorm上からも見えるようになった!!
image.png

動作確認

# デフォルトプロジェクトの起動
[DOCKER]$ yarn start
~省略
Compiled successfully!

You can now view app in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://172.17.0.2:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.

ブラウザでhttp://localhost:13000/ へアクセスし、デフォルトアプリが表示されることが確認できた!
image.png

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

Dockerコンテナに依存関係は全て閉じ込めてWebStormで開発 ~ローカルを汚さずにReactやFirebaseの環境構築を簡単に~

ローカル環境に色々入れずに開発環境をDocker上で構築したいけど、コーディングはIDEを使いたいので自分が辿り着いた手順をまとめました。
似たようなことをすればIntelliJ, PyCharm, GoLand, RubyMine, PhpStormでもできそう。

できること

  • ローカルPCにnodeなどを入れずにReactやFirebaseのアプリを開発できる
  • Firebaseの複数プロジェクトに対してデプロイしたい場合、アプリのディレクトリごとにFirebaseプロジェクトを割り当てられるので毎回firebase loginで切り替えずにデプロイできる

前提

  • WebStorm(or IntelliJ)をインストールしている
  • MacでDocker for Macをインストールしている

WebStormで新規Project作成

[File] -> [New] -> [Project]
image.png

[Empty Project]を選択し、Locationにプロジェクト名を設定して[CREATE]

Setting Value Remark
Location: {PROJECT PATH} PATHの末尾がプロジェクト名

image.png

空のプロジェクトが作成される
image.png

Dockerの設定

コマンドラインかWebStormのGUIのどちらかで設定すれば良い

Dockerfileを利用してコマンドラインで設定する場合

Terminalで以下を実行したあと、Ctrl + p->Ctrl + qで接続したコンテナから抜ける

[LOCAL]$ docker run \
-it \
-p 13000:3000 \
-v {PROJECT PATH}:/app \
--name {CONTAINER NAME} \
-w /app \
node:lts-alpine
Setting Value Remarks
-p 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする。何個も起動させる場合、HOST側のportは重ならないように変えること。
-v {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリと先ほどLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる。
--name {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
-w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

WebStormのDockerプラグインで設定する場合

[WebStorm] -> [Preferences...] で [Build, Execution, Deployment]にあるDockerの設定画面を選択し、+ボタンで新規作成
image.png
image.png

Docker for Macを利用しているので、これを選択し適当に名前をつけて[OK]を選択
image.png

(今回は画面の左下に)Dockerのタブが現れたので(Connect)を押すと、ConnectedとなりContainersImagesというのが表示される
image.png
image.png

Imagesを選択してPull Image
image.png

今回はnode:lts-alpineを利用

Setting Value Remarks
Registry: registry.hub.docker.com デフォルトの設定
Repository: node
Tag: lts-alpine ここは好きなのを選んで良い。今回は軽量と聞くalpineのlts版にした

image.png

Imagesに選択したDockerのimageが表示される
image.png

このimageからコンテナ作成のため+->Create..
image.png
image.png

コンテナ起動の設定を以下のようにしてRUN

Setting Value Remarks
Container name: {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
Bind ports: 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする
Bind mounts: {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリとLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる
Run options: -w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

image.png

Deploy logにコンテナ作成が成功されたログが表示されればOK
image.png

Reactのプロジェクト作成

TerminalからDockerコンテナに接続して、Docker上にReactプロジェクトを作成する

# コンテナの起動確認
[LOCAL]$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
febece633a44        aa57b0242b33        "node"              About a minute ago   Up About a minute   0.0.0.0:13000->3000/tcp   node-docker

# コンテナへ接続
[LOCAL]$ docker exec -it node-docker /bin/sh
/app # 

ここからdocker上での実行コマンド
コンテナシェルのPS1部分/app #[DOCKER]$に読みかえてる
https://facebook.github.io/create-react-app/docs/adding-typescript を参考にtypescriptのReactプロジェクトを作成

# nodeのversion確認
[DOCKER]$ node --version
v10.15.3

# /appディレクトリにプロジェクト作成
[DOCKER]$ npx create-react-app /app --typescript
npx: installed 63 in 3.522s

Creating a new React app in /app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

yarn add v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "linux" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.4: The platform "linux" is incompatible with this module.
info "fsevents@1.2.4" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 13 new dependencies.
info Direct dependencies
├─ @types/jest@24.0.11
├─ @types/node@11.13.4
~ 省略 ~

Your tsconfig.json has been populated with default values.


Success! Created app at /app
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd /app
  yarn start

Happy hacking!

Dockerコンテナの/appディレクトリに作成されたプロジェクトがWebStorm上からも見えるようになった!!
image.png

動作確認

# デフォルトプロジェクトの起動
[DOCKER]$ yarn start
~省略
Compiled successfully!

You can now view app in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://172.17.0.2:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.

ブラウザでhttp://localhost:13000/ へアクセスし、デフォルトアプリが表示されることが確認できた!
image.png

あとは好きに開発するだけ!!

FirebaseプロジェクトごとにDocker開発環境を作成

WebStormで新規Project作成しておく

# firebaseを利用するためまずはnodeのimageからコンテナを起動させる
[LOCAL]$ docker run \
-it \
--name firebase-skeleton \
-v {WEBSTORM PROJECTPATH}:/app \
-w /app \
node:lts-alpine

# 起動したコンテナに接続する
[LOCAL]$ docker exec -it firebase-skeleton /bin/sh

# firebaseのツールをインストール
[DOCKER]$ npm install -g firebase-tools
# 手順にしたがって利用したいgoogleアカウントでログインする
[DOCKER]$ firebase login --no-localhost
# Firebaseプロジェクトを選択or新規作成し、セットアップする(今回はCloud Functionsをセットアップ)
[DOCKER]$ firebase init functions

# ログイン状態のコンテナをcommitしてimage化する
[LOCAL]$ docker stop firebase-skeleton
[LOCAL]$ docker commit firebase-skeleton {FIREBASE PROJECT NAME}:{YOUR TAG}
# 不要になったコンテナは削除
[LOCAL]$ docker rm firebase-skeleton

# imageが作成されていることの確認
[LOCAL]$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
{FIREBASE PROJECT NAME}     {YOUR TAG}          c939d073f6a0        8 seconds ago       297MB
node                        lts-alpine          aa57b0242b33        4 days ago          71MB
# 指定したFirebaseプロジェクトにログイン状態のimageをコンテナ起動
[LOCAL}$ docker run \
-it \
--name {CONTAINER NAME} \
-v {WEBSTORM PROJECTPATH}:/app \
-w /app \
myfirebase/{FIREBASE PROJECT NAME}:{YOUR TAG}

WebStormでファイルを修正できるようになるのでfunctionを作成
今回はTypeScriptでCloud Functionsを作成するのでfunctions/src/index.tsをWebStormから変更
image.png

index.ts
import * as functions from 'firebase-functions';

export const helloWorld = functions.https.onRequest((request, response) => {
 response.send("Hello from Firebase!!!!");
});

動作確認

ログイン状態のimageを利用しているのでloginせずにFirebaseへデプロイできる!!

# 起動したコンテナに接続する
[LOCAL]$ docker exec -it {CONTAINER NAME} /bin/sh

# functionを作成してデプロイ(init時にTypeScriptを選択していると、このコマンド内でtsのコンパイルもしてくれる)
[DOCKER]$ firebase deploy --only functions
~省略~
✔  functions: Finished running predeploy script.
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (33.39 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: creating Node.js 6 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful create operation. 
Function URL (helloWorld): https://XXXXXXX.cloudfunctions.net/helloWorld

✔  Deploy complete!

Please note that it can take up to 30 seconds for your updated functions to propagate.
Project Console: https://console.firebase.google.com/project/{FIREBASE PROJECT NAME}/overview

Function URLで表示されたURLへアクセス
image.png

これで複数のFirebaseプロジェクトへデプロイしたい場合に、ローカルでloginを切り替えずに実行できる!!

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

WebStormとDockerでlocalにnodeを入れずにReactの開発環境を作成

前提

  • WebStorm(or IntelliJ)をインストールしている
  • MacでDocker for Macをインストールしている

WebStormで新規Project作成

[File] -> [New] -> [Project]
image.png

[Empty Project]を選択し、Locationにプロジェクト名を設定して[CREATE]

Setting Value Remark
Location: {PROJECT PATH} PATHの末尾がプロジェクト名

image.png

空のプロジェクトが作成される
image.png

Dockerの設定

コマンドラインかWebStormのGUIのどちらかで設定すれば良い

Dockerfileを利用してコマンドラインで設定する場合

Terminalで以下を実行

[LOCAL]$ docker run \
-it \
-p 13000:3000 \
-v {PROJECT PATH}:/app \
--name {CONTAINER NAME} \
-w /app \
node:lts-alpine
Setting Value Remarks
-p 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする。何個も起動させる場合、HOST側のportは重ならないように変えること。
-v {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリと先ほどLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる。
--name {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
-w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

WebStormのDockerプラグインで設定する場合

[WebStorm] -> [Preferences...] で [Build, Execution, Deployment]にあるDockerの設定画面を選択し、+ボタンで新規作成
image.png
image.png

Docker for Macを利用しているので、これを選択し適当に名前をつけて[OK]を選択
image.png

(今回は画面の左下に)Dockerのタブが現れたので(Connect)を押すと、ConnectedとなりContainersImagesというのが表示される
image.png
image.png

Imagesを選択してPull Image
image.png

今回はnode:lts-alpineを利用

Setting Value Remarks
Registry: registry.hub.docker.com デフォルトの設定
Repository: node
Tag: lts-alpine ここは好きなのを選んで良い。今回は軽量と聞くalpineのlts版にした

image.png

Imagesに選択したDockerのimageが表示される
image.png

このimageからコンテナ作成のため+->Create..
image.png
image.png

コンテナ起動の設定を以下のようにしてRUN

Setting Value Remarks
Container name: {CONTAINER NAME} 起動したコンテナにつける名前。今回はnode-dockerとしている。
Bind ports: 13000:3000 HOST:DOCKERの順で設定し、DockerコンテナのportへLocalからアクセスできるようにする
Bind mounts: {PROJECT PATH}:/app HOST:DOCKERの順で設定し、Dockerコンテナの/appディレクトリとLocalで作成したWebStormのプロジェクトディレクトリへ同期させることができる
Run options: -w app コンテナ起動時に/appディレクトリを作成してコンテナへ接続した時のデフォルトディレクトリになる

image.png

Deploy logにコンテナ作成が成功されたログが表示されればOK
image.png

TerminalからDockerコンテナに接続してプロジェクト作成

# コンテナの起動確認
[LOCAL]$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
febece633a44        aa57b0242b33        "node"              About a minute ago   Up About a minute   0.0.0.0:13000->3000/tcp   node-docker

# コンテナへ接続
[LOCAL]$ docker exec -it node-docker /bin/sh
/app # 

ここからdocker上での実行コマンド
コンテナシェルのPS1部分/app #[DOCKER]$に読みかえてる
https://facebook.github.io/create-react-app/docs/adding-typescript を参考にtypescriptのReactプロジェクトを作成

# nodeのversion確認
[DOCKER]$ node --version
v10.15.3

# /appディレクトリにプロジェクト作成
[DOCKER]$ npx create-react-app /app --typescript
npx: installed 63 in 3.522s

Creating a new React app in /app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

yarn add v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "linux" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.4: The platform "linux" is incompatible with this module.
info "fsevents@1.2.4" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 13 new dependencies.
info Direct dependencies
├─ @types/jest@24.0.11
├─ @types/node@11.13.4
~ 省略 ~

Your tsconfig.json has been populated with default values.


Success! Created app at /app
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd /app
  yarn start

Happy hacking!

Dockerコンテナの/appディレクトリに作成されたプロジェクトがWebStorm上からも見えるようになった!!
image.png

動作確認

# デフォルトプロジェクトの起動
[DOCKER]$ yarn start
~省略
Compiled successfully!

You can now view app in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://172.17.0.2:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.

ブラウザでhttp://localhost:13000/ へアクセスし、デフォルトアプリが表示されることが確認できた!
image.png

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

OpenPose の Docker イメージの作成方法

環境

OS: Ubuntu 16.04.6 LTS
GPU: Geforce GTX1060
NVIDIA ドライバ: 390.87

nvidia-docker2 のインストール

下記の記事を参考に nvidia-docker2 をインストール
https://qiita.com/spiderx_jp/items/32c421fd00c6ade19720

デフォルトランタイムの変更

Docker イメージのビルド時に cuda を参照できるよう、下記のファイルへ"default-runtime": "nvidia", を追加

/etc/docker/daemon.json
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

Docker イメージのビルド

下記の Dockerfile を使ってイメージをビルドする

Dockerfile
FROM nvidia/cuda:8.0-cudnn5-devel

MAINTAINER @kndt84

RUN apt update && \
  apt install -y --no-install-recommends\
    sudo \
    git \
    wget \
    cmake \
    libopencv-dev

WORKDIR /opt
RUN git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose.git

RUN /bin/sh /opt/openpose/scripts/ubuntu/install_deps.sh

WORKDIR /opt/openpose/3rdparty
RUN git clone https://github.com/BVLC/caffe.git && \
  cd caffe && \
  git checkout f019d0dfe86f49d1140961f8c7dec22130c83154

WORKDIR /opt/openpose
RUN mkdir build && \
  cd build && \
  cmake .. && \
  make -j `nproc` && \
  make install

CMD echo "Finished!"

ビルドを実行する

docker build . -t openpose

OpenPose の実行

USBカメラを接続して下記のコマンドを実行する

docker run --rm \
  --net host \
  -e DISPLAY=$DISPLAY \
  -v $HOME/.Xauthority:/root/.Xauthority \
  --privileged \
  openpose ./build/examples/openpose/openpose.bin --face --hand
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでLaravel環境を構築する②~MySQL、laravelの導入~]

DockerでLaravel環境を構築する②~PHPの導入~の続きです。これで最後です。

MySQLのインストール

次にDBを使えるようにするため、MySQLをインストールしていきます。

docker-compose.yml
services:
# 省略
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

environmentはDockerコンテナ内で使用する環境変数を指定できます。
ただしこれで終わりではなく、最後に(laravelをインストールした後に)
今設定したこれらの値を、laravelのアプリ内に設定することで、実際にmysqlを使えるようにしていきます。

また、volumesによって、mysqlのデータを永続化しています。
最終的なdocker-compose.ymlは以下のようになります。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:1.15.6
    ports:
      - "8000:80"
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7.2-fpm
    depends_on:
    - mysql
    volumes:
      - .:/var/www/html
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

Laravelのインストール

次は、Laravelをインストールします。

laravelのインストールにはcomporserが必要ですが、最初に作成したPHPにはそれがありません。なので,
imageを取得してPHPを立ち上げるのではなく、「phpのimage+comporserのインストール」ができるDockerfileを作成します。
dockerディレクトリの下にphpというディレクトリを作り、そこにDockerfileを作成し、内容を以下のようにします。

docker/php/Dockerfile ↓

FROM php:7.2-fpm

# install composer
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim

RUN apt-get update \
    && apt-get install -y libpq-dev \
    && docker-php-ext-install pdo_mysql pdo_pgsql

WORKDIR /var/www/html

次に、docker-compose.yml内のappサービスを以下のように書き換え、「build: ./docker/php」で、Dockerにホストされているimageからではなく、
作成したDockerfileからビルドするようにします。

docker-compose.yml
app:
    build: ./docker/php
    depends_on:
      - mysql
    volumes:
      - .:/var/www/html

そして、Nginxの設定(docker/default.conf)のroot(ドキュメントルート、4行目あたり)を書き換えて以下のようにします。

root  /var/www/html/my-laravel-app(自分の作成したlaravelアプリの名前)/public;

これで、nginxをリスタートします。

docker-compose restart

再度アクセスし、

スクリーンショット 2019-04-13 13.57.55.png

このようになればOKです!

最後に、(MySQLのインストールの続き)
環境変数の各値を、Laravel内のプロジェクトの .envファイルに記入します。

$ cd my-laravel-app(作成したlaravelのアプリに移動)
$ vi .env 

こんな感じで、.envファイルを開き、

以下のようになっている箇所を

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

docker-compose.ymlで定義した内容に合わせ、このように変更してください。

DB_HOSTのところは、docker-composeで定義したサービス名になります。

.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=sample
DB_USERNAME=user
DB_PASSWORD=password

以上で、作成したlaravelアプリで、mysqlが使えるようになっています。

nginxをリスタートし

$ docker-compose restart

再度アクセスして、コンテナの中に入ります。

$ docker-compose exec app bash
root@xxxxxxxxx:/var/www/html# 

#で入力待ちになっていればOKです。

作成したlaravelのアプリに移動して、マイグレーションを実行し、以下のようになれば完成です!!

root@xxxxxxxxx:/var/www/html#  cd my-laravel-app(作成したlaravelのアプリに移動)
root@xxxxxxxxx:/var/www/html#  php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

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

docker-composeの覚えていた方がよさそうなコマンド

dockerが使えるようになると、WindowsやMacやLinuxとかあまり気にしなくなってきますね

docker runするのではなく、docker-composeやdockerfileを使って「インフラのコード化」をしておけば、
ローカルPCだけでは無く、オンプレ環境やクラウド上(AWS・GCP・Azureなど)にも比較的簡単に移行できます

docker-composeファイルを自ら作成しない人でも、コマンドはある程度知っていてもいいと思います
※Kubernetes関連がもう少し簡単になればdocker-composeコマンド自体も使わなくなるかもしれませんが…

docker-composeの覚えていた方がよさそうなコマンド

前提

docker-compose.yaml
があるフォルダに移動します。


プロセス確認

docker-compose ps

作業前に必ず確認するようにするといいと思います。


実行

docker-compose up

で起動します(初回起動時はイメージのダウンロードやビルドも自動で開始します)

止める場合は

Ctrl+C

を押下します

docker-compose.yaml
ファイルを編集した後に設定を反映させる場合も

docker-compose up

を実行します

問題なさそうであれば

Ctrl+C

で止めた後

docker-compose start

でバックグラウンドで実行されます

ログの確認が元からいらないのであれば、バックグラウンドで実行の-dをつけて起動することもできます

docker up -d

イメージ内のコマンドラインに入る

docker-compose exec サービス名 /bin/bash

または

docker-compose exec サービス名 /bin/sh

ログ確認

docker-compose logs [サービス名] -t 

 時間指定で確認したい場合は
 ※docker-composeのlogsにsinceオプションがない?のでdockerコマンド

docker logs コンテナ名 -t --since "2019-04-13 03:55:00Z"

その他コマンド

開始

docker-compose start

停止

docker-compose stop

再起動

docker-compose restart

削除

docker-compose rm

停止+削除

docker-compose down

ビルド

docker-compose build

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

Python/NLP/機械学習のためのDocker環境構築

Docker上でPython+自然言語処理+基本的な機械学習を行うための環境構築方法について説明します.
また,Dockerについての基本的な知識があることを前提としています.

導入するもの

  • ベース
    • Alpine Linux 3.9
  • Python
    • Python 3.7.3
    • numpy
    • scipy
    • scikit-learn
    • gensim
  • 自然言語処理
    • mecab
    • cabocha

実行環境

  • Ubuntu 18.04 LTS
  • Docker 18.09.5

Alpine Linux

Alpine Linuxは, 軽量なLinuxディストリビューションです.
Dockerイメージを簡単に軽量化できることから,ベースイメージとして多く採用されています.

ただし,Alpineはデフォルトではかなり機能が制限されています.
そのため,追加で色々なツールやパッケージをインストールしていく必要があります.

各種ファイルの作成

Dockerfile

Dockerfile
# ベースイメージ
FROM python:3.7.3-alpine3.9

# 環境変数
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
ENV PYTHONUNBUFFERED 1

# 各種パッケージのインストール
RUN apk add --update bash git curl build-base swig gfortran linux-headers

# Mecab
RUN cd /tmp \
    && git clone https://github.com/taku910/mecab.git \
    && cd mecab/mecab/ \
    && ./configure --enable-utf8-only --with-charset=utf8 \
    && make \
    && make install \
    && cd ../mecab-ipadic \
    && ./configure --with-charset=utf8 \
    && make \
    && make install

# CRF++ (Cabochaで必要)
RUN wget -O /tmp/CRF++-0.58.tar.gz 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7QVR6VXJ5dWExSTQ' \
    && cd /tmp/ \
    && tar zxf CRF++-0.58.tar.gz \
    && cd CRF++-0.58 \
    && ./configure \
    && make \
    && make install

# Cabocha
RUN cd /tmp \
    && DOWNLOAD_URL="https://drive.google.com`curl -c cookies.txt \
       'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7SDd1Q1dUQkZQaUU' \
       | sed -r 's/"/\n/g' |grep id=0B4y35FiV1wh7SDd1Q1dUQkZQaUU |grep confirm |sed 's/&amp;/\&/g'`" \
    && curl -L -b cookies.txt -o /tmp/cabocha-0.69.tar.bz2 "$DOWNLOAD_URL" \
    && tar jxf cabocha-0.69.tar.bz2 \
    && cd cabocha-0.69 \
    && ./configure --with-mecab-config=`which mecab-config` --with-charset=utf8 \
    && make \
    && make install \
    && cd python \
    && python setup.py build \
    && python setup.py install \

# LAPACK/BLAS (scikit-learnで必要)
RUN cd /tmp \
    && wget http://www.netlib.org/lapack/lapack-3.8.0.tar.gz \
    && tar zxf lapack-3.8.0.tar.gz \
    && cd lapack-3.8.0/ \
    && cp make.inc.example make.inc \
    && make blaslib \
    && make lapacklib \
    && cp librefblas.a /usr/lib/libblas.a \
    && cp liblapack.a /usr/lib/liblapack.a \
    && cd / \
    && rm -rf /tmp/*

# pip
COPY requirements.txt /home
WORKDIR /home
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

requirements.txt

pipでインストールするパッケージを記載します.
バージョンを指定したい場合は numpy==1.16.2 のようにしてください.
今回は必要最低限なものしかインストールしません.

requirements.txt
mecab-python3
numpy
scipy
scikit-learn
gensim

Dockerイメージを作成

Dockerfileとrequirements.txtを同じディレクトリに置きます.
以下のコマンドでDockerビルド(Dockerイメージを作成するコマンド)を実行します.

※Cabochaのダウンロードに失敗してビルドができないことがあります.
少し時間をおきながら何度か再実行してみて下さい.

$ cd <Dockerfileが存在するディレクトリ>
$ docker build -t nlp-ml:1 .
 (docker build -t <Dockerイメージ名> <Dockerfileが存在するディレクトリ>)

$ docker images
REPOSITORY  TAG   IMAGE ID       CREATED         SIZE
nlp-ml      1     4b7930388f08   3 minutes ago   93.5MB

これでDockerイメージが作成できました.
このDockerイメージを使用して,コンテナを起動します.

$ docker run -it --name hoge nlp-ml:1 bash
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

circleci+docker-compose備忘録

machine.imageはcircleci/classic

version: 2
jobs:
  build:
   machine:
    image: circleci/classic:edge

docker-composeを普通に使えるように

イメージキャッシュ

      - restore_cache:
          keys:
            - docker-image-{{ checksum "app.Dockerfile.development" }}

      - run:
          name: docker image cache
          command: |
            if [ ! -f ~/caches/images.tar ]; then
              docker-compose build app
              mkdir -p ~/caches
              docker save -o ~/caches/images.tar $(docker images --filter "dangling=false" --format "{{.Repository}}:{{.Tag}}")
            fi
      - save_cache:
          key: docker-image-{{ checksum "app.Dockerfile.development" }}
          paths:
           - ~/caches/images.tar

      - run:
          name: load docker images
          command: docker load -i ~/caches/images.tar

buildしたもののみキャッシュしてます

volume cache

      - restore_cache:
          keys:
            - gemfile_lock-cache-{{ checksum "Gemfile.lock" }}

      - restore_cache:
          keys:
            - yarn_lock-cache-{{ checksum "yarn.lock" }}

      - restore_cache:
          keys:
            - bundle-cache-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
            - bundle-cache-{{ .Branch }}
            - bundle-cache

      - restore_cache:
          keys:
            - node_modules-cache-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - node_modules-cache-{{ .Branch }}
            - node_modules-cache

      - run:
          name: docker volume restore
          command: |
            if [ -f ~/caches/bundle-data.tar.bz2 ]; then
              cat ~/caches/bundle-data.tar.bz2 | docker run -i -v project_bundle-data:/volume --rm loomchild/volume-backup restore -
            fi
            if [ -f ~/caches/node_modules-data.tar.bz2 ]; then
             cat ~/caches/node_modules-data.tar.bz2 | docker run -i -v project_node_modules-data:/volume --rm loomchild/volume-backup restore -
            fi
      - run:
          name: bundle install && yarn install
          command: |
            docker-compose run --rm app sh -c "bundle install && yarn install"
      - run:
          name: create docker volume tarball
          command: |
            if [ -f ~/caches/Gemfile.lock ]; then
              md5sum ~/caches/Gemfile.lock > gemfile_lock_hash.txt
              if ! md5sum -c gemfile_lock_hash.txt; then
                docker run -v project_bundle-data:/volume --rm loomchild/volume-backup backup - > ~/caches/bundle-data.tar.bz2
              fi
            else
              docker run -v project_bundle-data:/volume --rm loomchild/volume-backup backup - > ~/caches/bundle-data.tar.bz2
            fi
            if [ -f ~/caches/yarn.lock ]; then
              md5sum ~/caches/yarn.lock > yarn_lock_hash.txt
              if ! md5sum -c yarn_lock_hash.txt; then
                docker run -v project_node_modules-data:/volume --rm loomchild/volume-backup backup - > ~/caches/node_modules-data.tar.bz2
              fi
            else
              docker run -v project_node_modules-data:/volume --rm loomchild/volume-backup backup - > ~/caches/node_modules-data.tar.bz2
            fi
      - run:
          name: copy Gemfile.lock and yarn.lock for cache
          command: |
            cp Gemfile.lock ~/caches/Gemfile.lock
            cp yarn.lock ~/caches/yarn.lock
      - save_cache:
          key: gemfile_lock-cache-{{ checksum "Gemfile.lock" }}
          paths:
           - ~/caches/Gemfile.lock

      - save_cache:
          key: yarn_lock-cache-{{ checksum "yarn.lock" }}
          paths:
           - ~/caches/yarn.lock

      - save_cache:
          key: bundle-cache-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
          paths:
           - ~/caches/bundle-data.tar.bz2

      - save_cache:
          key: node_modules-cache-{{ .Branch }}-{{ checksum "yarn.lock" }}
          paths:
           - ~/caches/node_modules-data.tar.bz2

node_modulesとbundleのvolumeをキャッシュするようにしてます。
lockファイルをキャッシュしておき前回のものとハッシュ値を比較して、ハッシュ値が異なる場合にvolumeのバックアップを作成し直してキャッシュするようにしてます。

参考文献

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

docker-entrypoint-initdb.d に設置したスクリプトで localhost に接続できずにハマったお話

やりたいこと

ゴールは embulk で外部の DB から docker 内の postgres へデータを入れることです。
それを docker-entrypoint-initdb.d 内のスクリプトで解決したいのですがその過程でハマったのでまとめておきます。

解決策

先に解決策を書いておくと、localhost への接続を行う前に、下記のコマンドを実行することで解決されます。

pg_ctl -o "-c listen_addresses='localhost'" -w restart

調査

docker-entrypoint-initdb.d に設置してあるスクリプトから embulk を実行していたのですが、出力先である localhost の postgress への接続に失敗していました。
いったん、docker-entrypoint-initdb.d に設置したスクリプトから embulk の処理を削除し、コンテナを立ち上げたあとにスクリプトを実行すると正しく動作しました。
なので、docker-entrypoint-initdb.d での処理が怪しいと考え調査しました。

docker-entrypoint-initdb.d はどう処理されているのか

docker-entrypoint-initdb.d に設置されたスクリプトは docker-entrypoint.sh にて実行されます。
ですので、docker-entrypoint.sh を読んでいくことにしました。
すると以下のようなコメントが見つかりました。

docker-entrypoint.sh

124     # internal start of server in order to allow set-up using psql-client
125     # does not listen on external TCP/IP and waits until start finishes
126     PGUSER="${PGUSER:-$POSTGRES_USER}" \
127     pg_ctl -D "$PGDATA" \
128       -o "-c listen_addresses=''" \
129       -w start

要するに外部からの接続は許可していないということと認識しました。

localhost へ接続したい

調査を進めていくと、下記の issue に行き当たりました

psql -h localhost fails in init script · Issue #474 · docker-library_postgres

こちらに冒頭に記載したコマンドによる解決策が掲示されており、無事解決されたというお話でした。

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

なかなか入門できなかった人のためのdocker(+go)入門以前 part1

まえがき

goのプログラムをdockerで動かしたい、あわよくばk8sでデプロイしたいシリーズ第二弾です。
この part1 では、 docker run してdocker上でプログラムを動作させるところまでを扱います。


流行りのdockerですが、なかなか波に乗り切れず、ローカル開発環境の方が簡単じゃない? と思ってしまっているうちにだいぶ時間が経ってしまいました。

これ以上化石になってしまわないように、なんとかdockerに入門したい。あわよくばgoを動かしたい。そんな記事です。

なお、先々にk8sでのデプロイを目論んでいる関係もあり、この記事ではdocker-compose1を扱いません。

想定読者

  • dockerよくわからない
  • docker使いたい
  • 急に複雑な構成が出てきても困る
  • オプションとかの細かい説明や「これが最強だ」みたいなハイテクコマンドが出てくると理解を拒否してしまう
  • ローカル環境やVagrantでなら非常に初歩的なことで躓いてdocker入門しきれてない
  • 環境構築的には、Vagrantfile(そこまで深くはわからんけど)いじったことあるよーぐらいのレベルの人

あまり想定していない読者

  • docker-composeの使い方を学びたい
  • goの最低限の動かし方を知りたい
    • 第一弾の記事を前提にこの記事では説明を進めるので、記事内でのgoに関する説明はあまりありません
  • webサーバーとか仮想環境とかなんのことだかよくわからない、ぐらいのレベルの人
    • ローカルwebサーバーとしてのdockerの立ち上げ方の説明を試みているので、そのあたりの前提になっている知識の説明が少ない可能性があります。
  • Windowsの方
    • 筆者がMacを使っていてMacの環境を前提に説明するので、Windowsの方に全然優しくない説明の可能性が高いです

dockerの特徴について

以下のような特徴があり、旧来の勢力であるローカル開発環境やVagrantのいいとこ取りがしやすいとのことで、近年急激に普及してきています。

  • 配布可能な仮想環境
    • DockerfileによってIac(Infrastructure as Code)が実現でき、共通の開発環境を簡単に配布できます
  • コンテナ型仮想化
    • コンテナと呼ばれる技術(というか、考え方?)を用いて環境構築をします。
    • イメージとしては、OSをdockerがエミュレート2してくれて、開発に実際に関係ある部分だけ都度環境構築するイメージ
    • 従来型のホスト型仮想化と呼ばれる形式と比べて軽量に動作しやすいです3
  • Kubernetes(通称k8s)などのコンテナオーケストレーションサービスとの連携
    • 連携しやすかったです(感想)。GKEでは作ったコンテナをCloud Registryに追加して画面ぽちぽちするだけでデプロイできました。
    • よりスケーラブルな話はまたいつか

以下の記事の方がよりわかりやすかったり、詳しかったりしそうです。

さて、入門以前に入っていきましょう。
動かすまでの手順というイメージです。

dockerをインストールする

docker公式サイトからインストールしてきましょう。

右上のGet Startedから、Get Started with Dockerのページに行って、 Download for Mac をクリックします。

DockerHubのDocker Desktop for Macというページに飛ばされるので、サインアップなどを済ませて Get Docker しましょう。

Docker.dmg

というファイルがダウンロードできたら、展開してインストールを進めます。
しばらくGUIの指示に従ってインストールを進めると、処理が完了しdockerが使えるようになります。

terminal上で

docker -v

として、

Docker version 18.09.2, build 6247962

のような表示が出れば成功です。(インストールだけは昔からしているので、↑はちょっと古いかも)

dockerを動かす

dockerを動かすまでには、いくつかのステップがあります。
最低限以下のことがわかっていれば、dockerを試すところまではいけると思います。

  • docker imageを取得する
  • docker imageからコンテナを起動する

それでは早速やっていきましょう。

docker imageを取得する

以下のコマンドを打てば取得できます。

docker pull golang:1.12.3-alpine3.9

このコマンドについてもうちょっとだけ説明していきます。
まず、

docker pull image名:タグ名

とすることで、 docker registry と呼ばれる docker image が保管されている場所から docker image を取得してくることができます。

取得してきた docker image の一覧は

docker images

を実行することで確認できます。

docker imageってなに?

とはいえ docker image って何よ、という話なのですが、端的にいうと「サーバーの設計書」です。
docker は docker image があれば、 docker container と呼ばれるサーバーをセットアップし、起動することができるのです。

今回でいうと、 golang というのが docker image の名称になります。

docker imageのタグについて

では、例にあるコマンドの 1.12.3-alpine3.9 ってなんなのでしょうか。
これはタグと呼ばれる情報で、取得するイメージのバージョンや環境などを選択できます。

1.12.3 の部分はgoのバージョンを表しています。

そのあとはモノによるのですが、今回のように追加情報が記載されていることがあります。

stretch と alpine について

golang イメージには主だったもので stretch 系と alpine 系のタグが存在します。

タグごとに docker image を定義している Dockerfile の記載が異なるので、動作が異なります。
stretch系はdebian系のimageで、 g++, gcc, libc あたりの機能をはじめにインストールしているみたいです。純粋にgolangを動かしたい方に向いている印象です。

alpine系はlinux系のimageで、あらかじめ bash, openssl などをインストールしているため通信系の機能などを含むアプリケーションの場合は取り回しがしやすいです。簡易的にWebAPIを作りたいようなときはこちらが便利そうですね。

色々と使いやすいのもあり、今回は 1.12.3-alpine3.9 を利用します。

なお、Dockerfileのレベルで確認したい方は以下のリンクが参考になります。
docker、最初はとっつきづらいなと思っていたんですが、慣れてくるとあらゆる情報がDockerHubなどを通じて公開されているのでこういうところがとても追いかけやすいなあ、と感じました。

docker imageからコンテナを起動する

docker run image名:タグ名

で起動できます4

このコマンドで起動され立ち上がったサーバーのことを、 dockerコンテナと呼びます。

起動時の動作に指定がない docker image の場合、上記のコマンドは成功しますがその後何も起きません。

コンテナ起動時には、パターンに応じて以下のオプションを理解しておくと良いと思います。

dockerコンテナのなかでbash等のコマンドを実行したい

bashなどのコマンドを実行したい場合、 -it オプションを用います。5

docker run -it image名:タグ名

dockerコンテナをホストマシンのディレクトリでマウントして、webサーバーとして起動したい

開発用のwebサーバーとしてdockerコンテナを起動したい場合、

  • 手元のコードを反映してほしい
  • ローカルマシンから localhost:8080 とかでアクセスできるサーバーとして立ち上がってほしい

というニーズがあると思います。
その実現にあたっては、ざっくり以下のことを把握しておくと良いと思います。

  • -p オプションで port forwarding
  • -v オプションで マウント元とマウント先の指定
  • -e オプションで 環境変数の指定
  • -d オプションで バックグラウンド実行
  • -it オプション + image:tag の後にコマンドを記載することで、webサーバー起動コマンドの流し込み

上記を踏まえた実行時のterminalのイメージは以下のような感じ。
/path/to/host/path/to/docker は仮のパスなので適宜読み替えてくださいませ。

docker run -it \                                     # コンテナ内部に入ってbashの操作を行う。最終行でコマンド指定
           -p 8080:8080 \                            # ホストマシンのポートとdockerコンテナのポートを接続する。
           -v /path/to/host/go:/path/to/docker/go \  # ホストマシンのディレクトリ情報でdockerコンテナの中身をマウントする。フルパスじゃないと動かないかも
           -e ENV_VARIABLE=env_value \               # 環境変数の指定
           -e ENV_VARIABLE2=env_value2 \             # 環境変数を複数指定する場合は繰り返し用いる
           -d \                                      # バックグラウンド実行
           image:tag \                               # 使用するdocker imageの指定。確か公式リポジトリにあるやつならdocker runするときに取ってきてくれる
           go run main.go /path/to/docker/go/main.go # 実行するコマンド。 -it コマンドの初期値として与えることができる

なお、 docker run の際にはタグ名を省略することもできますが、同じ名称のimageを複数pullしてきている場合はタグまで書いた方がわかりやすいです。

ここで起動されたサーバーのことをdocker containerと呼びます。

なお、コンテナを動かすにあたっては、こちらの記事がより参考になります。コマンドの実例集は本当にありがたい。。

起動したコンテナを使って開発や動作確認をする

動く docker run コマンドの例を書いてみます。
とりあえず動かしたい! という方は真似してみてください。

事前に、上記のdocker imageを取得しておいてください。

一旦仮定として、以下のパスにいることにしましょう。
/YOUR_USER_NAMEtestproject は適宜読み替えをお願いします。
また、 $GOPATH は ~/go という仮定で話を進めます。

pwd #=> /Users/YOUR_USER_NAME/go/src/github.com/testproject/

ここでいつものサンプルを作成します。

/Users/YOUR_USER_NAME/go/src/github.com/testproject/main.go
package main

import "github.com/gin-gonic/gin"

func main() {
  r := gin.Default()
  r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
      "message": "pong",
    })
  })
  r.Run() // listen and serve on 0.0.0.0:8080
}

この状態で、以下のようなコマンドを実行します。

docker run -it \
           -p 8080:8080 \
           -v /Users/YOUR_USER_NAME/go/src/github.com/testproject:/go/src/github.com/testproject \
           golang:1.12.3-alpine3.9 \
           go run /go/src/github.com/testproject/main.go

これを実行すると、 docker image を元にした docker container が起動し、ローカルサーバーが立ち上がります。

localhost:8080/ping

にアクセスして、 {"message": "pong"} のレスポンスが返ってくれば成功です。

その他のコマンドについて

以下を覚えておくと入門以前のレベルとしては十分だと思います。

docker images              # 手元にある docker image が確認できる
docker rmi [IMAGE ID]      # 指定したimageが削除できる。IMAGE IDは docker images で確認できる
docker ps                  # 起動中のコンテナが確認できる
docker kill [CONTAINER ID] # 指定したcontainerを停止できる。CONTAINER IDは docker ps で確認できる

Dockerfile使ったりdocker buildしたりしたい。そしてコンテナをデプロイしたい

そんな感じで、dockerのなんとなくの概要とかをまとめつつ、docker runでサーバーが起動するところまでを駆け足でまとめてみました。
Dockerfileってなに?
手元で動くだけじゃ困るんだけど?
みたいな悩みが本番デプロイやdocker imageの配布などを行いたい人には発生すると思うのですが、これは次回以降に続きます。続け!


  1. docker-composeとは、複数のdockerコンテナ(記事内で言及予定)を構成管理できるツールです。よくセットで出てくるけどdockerに対するメタツールなので必須ではないものです。例えばWebアプリケーションサーバーとしてのコンテナと、MySQLサーバーとしてのコンテナを同時に立ち上げ、接続設定まで済ませるといったことが可能です。この記事ではできる限りシンプルにdockerの動かし方を学びたい(しかもこれ書いてる人もdocker-composeよくわかってない)ため、言及していません 

  2. 完全に余談ですが、シミュレートは内部の動作を再現すること、エミュレートは目に見える動作を再現することを指すらしく、位置付けがけっこう異なるようです。高度に完成されたシミュレーションとエミュレーションは同じ結果をもたらす、とも言われています。 

  3. IE8を再現するためのVirtualBoxイメージとかね・・・ 

  4. Vagrantでの vagrant up にあたります 

  5. Vagrantでの vagrant up → vagrant ssh にあたります 

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