20200327のdockerに関する記事は19件です。

dockerで立てたpostgresをposticoからみる

やりたいこと

  • dockerで立てたpostgresをlocalからGUIで中身を見たい

postgresで見ようとした際にでたエラー

結構posticoでみるまでに苦労したのでかきに記しておく

https://teratail.com/questions/247008

上記のエラーが出た。原因を見つけるために下記を行う

database.ymlとdocker-compose.ymlの設定

passwordは必要?

https://docs.docker.com/compose/rails/

このドキュメントにはpassは省略してたが省略したら怒られた。たぶん必要。

POSTGRES_PASSWORDなどの設定

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./docker/pg:/var/lib/postgresql
    ports:
      - '5432:5432'
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: localhost
      POSTGRES_DB: test_db
  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

上記のようにpassなどの設定をする。ここをdatabase.ymlと合わせる。

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

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

psqlコマンドで開く

psqlのコマンドは下記

「psqlドキュメント」
https://www.postgresql.jp/document/9.2/html/app-psql.html

docker-compose run db psql -U localhost -d test_db -h db -p 5432

でposticoではなく直接みてみる。上記は下記の意味合い。

$ psql -U localhost(usernameの指定) -d test_db(dbnameの指定) -h localhost(hostnameの指定) -p 5433(portの指定)

詰まったときに助かったコマンド

すべてを消すコマンド

# すべてを無に帰す
$ docker-compose down --rmi all --volumes

参考:
https://qiita.com/suin/items/19d65e191b96a0079417

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

Rasa NLU で自然言語理解のおためし

NLU (Natural Language Understanding=自然言語理解) をやってみたくて、

https://tech.mof-mof.co.jp/blog/rasa-nlu-japanese.html

を参考にしながら、dockerで環境を作って、実際に動くところまでやってみる。

Docker環境構築

ホストマシン上でrasa用のディレクトリを作る。

$ mkdir rasa
$ cd rasa
$ vi Dockerfile

Dockerfile に、まずは python が動くimageのみを記述してみる。

FROM python:3.7-slim-stretch

docker-composeで動かしたいので docker-compose.yml を作成

$ vi docker-compose.yml
docker-compose.yml
version: '2'
services:
  rasa:
    container_name: rasa
    build:
      context: .
    volumes:
      - .:/app

buildする

$ docker-compose build 
Building rasa
Step 1/1 : FROM python:3.7-slim-stretch
 ---> c9ec5ac0f580
Successfully built c9ec5ac0f580
Successfully tagged rasa-test_rasa:latest

$

python動くか確認。

$ docker-compose run --rm rasa bash
Creating network "rasa-test_default" with the default driver
root@c02085da1f5f:/# python --version
Python 3.7.7
root@c02085da1f5f:/#

動いた。

Rasaをインストール

https://tech.mof-mof.co.jp/blog/rasa-nlu-tutorial.html

を参考にrasa環境を作っていく

root@c02085da1f5f:/# pip install rasa
...(なんかいろいろインストールされる)

Successfully built sanic-jwt absl-py mattermostwrapper colorclass webexteamssdk SQLAlchemy terminaltables future gast termcolor wrapt PyYAML docopt pyrsistent
Failed to build ujson
Installing collected packages: ujson, certifi, six, pycparser, cffi, cryptography, future, python-telegram-bot, tqdm, tabulate, python-crfsuite, sklearn-crfsuite, dnspython, pymongo, ruamel.yaml, numpy, h5py, keras-applications, opt-einsum, grpcio, protobuf, absl-py, google-pasta, gast, termcolor, scipy, wrapt, keras-preprocessing, werkzeug, cachetools, pyasn1, pyasn1-modules, rsa, google-auth, chardet, urllib3, idna, requests, markdown, oauthlib, requests-oauthlib, google-auth-oauthlib, tensorboard, tensorflow-estimator, astor, tensorflow, python-dateutil, PyYAML, docopt, pykwalify, zipp, importlib-metadata, pyrsistent, attrs, jsonschema, greenlet, gevent, redis, PyJWT, sanic-jwt, cloudpickle, kafka-python, rocketchat-API, joblib, scikit-learn, pysocks, pytz, twilio, cycler, pyparsing, kiwisolver, matplotlib, mattermostwrapper, multidict, psycopg2-binary, colorclass, aiofiles, rfc3986, hstspreload, hpack, hyperframe, h2, h11, sniffio, httpx, httptools, uvloop, websockets, sanic, requests-toolbelt, webexteamssdk, httplib2, oauth2client, python-engineio, tzlocal, apscheduler, async-generator, wcwidth, prompt-toolkit, questionary, fbmessenger, sanic-plugins-framework, sanic-cors, humanfriendly, coloredlogs, colorhash, jsonpickle, SQLAlchemy, async-timeout, yarl, aiohttp, pydot, packaging, rasa-sdk, python-socketio, tensorflow-hub, decorator, tensorflow-probability, typeguard, tensorflow-addons, terminaltables, networkx, jmespath, docutils, botocore, s3transfer, boto3, slackclient, pika, rasa
    Running setup.py install for ujson ... error
    ERROR: Command errored out with exit status 1:
     command: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-ingvl92n/ujson/setup.py'"'"'; __file__='"'"'/tmp/pip-install-ingvl92n/ujson/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-46isinhm/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.7m/ujson
         cwd: /tmp/pip-install-ingvl92n/ujson/
    Complete output (12 lines):
    Warning: 'classifiers' should be a list, got type 'filter'
    running install
    running build
    running build_ext
    building 'ujson' extension
    creating build
    creating build/temp.linux-x86_64-3.7
    creating build/temp.linux-x86_64-3.7/python
    creating build/temp.linux-x86_64-3.7/lib
    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I./python -I./lib -I/usr/local/include/python3.7m -c ./python/ujson.c -o build/temp.linux-x86_64-3.7/./python/ujson.o -D_GNU_SOURCE
    unable to execute 'gcc': No such file or directory
    error: command 'gcc' failed with exit status 1
    ----------------------------------------
ERROR: Command errored out with exit status 1: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-ingvl92n/ujson/setup.py'"'"'; __file__='"'"'/tmp/pip-install-ingvl92n/ujson/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-46isinhm/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.7m/ujson Check the logs for full command output.
root@c02085da1f5f:/# 

なんかエラー出た。

unable to execute 'gcc': No such file or directory ってことなので、それっぽいのをインストールする

root@c02085da1f5f:/# apt-get update -q -y && apt-get install -q -y build-essential
...(なんかいろいろインストールされる)

update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode
Setting up build-essential (12.3) ...
Processing triggers for libc-bin (2.24-11+deb9u4) ...
root@c02085da1f5f:/#

もっかいrasaのインストールにチャレンジ

root@c02085da1f5f:/# pip install rasa
...(なんかいろいろインストールされる)

Successfully built ujson
Installing collected packages: six, absl-py, cycler, python-dateutil, kiwisolver, numpy, pyparsing, matplotlib, docopt, PyYAML, pykwalify, protobuf, tensorflow-hub, kafka-python, pytz, multidict, pysocks, urllib3, certifi, idna, chardet, requests, PyJWT, twilio, fbmessenger, ruamel.yaml, yarl, attrs, async-timeout, aiohttp, slackclient, terminaltables, aiofiles, httptools, websockets, ujson, h11, hpack, hyperframe, h2, sniffio, rfc3986, hstspreload, httpx, uvloop, sanic, sanic-plugins-framework, sanic-cors, humanfriendly, coloredlogs, rasa-sdk, tzlocal, apscheduler, packaging, typeguard, tensorflow-addons, greenlet, gevent, pika, scipy, google-pasta, astor, termcolor, wrapt, grpcio, pyasn1, pyasn1-modules, rsa, cachetools, google-auth, werkzeug, markdown, oauthlib, requests-oauthlib, google-auth-oauthlib, tensorboard, h5py, keras-applications, tensorflow-estimator, keras-preprocessing, opt-einsum, gast, tensorflow, cloudpickle, decorator, tensorflow-probability, dnspython, pymongo, python-engineio, joblib, scikit-learn, httplib2, oauth2client, SQLAlchemy, requests-toolbelt, future, webexteamssdk, sanic-jwt, wcwidth, prompt-toolkit, colorhash, colorclass, tqdm, rocketchat-API, jmespath, docutils, botocore, s3transfer, boto3, questionary, zipp, importlib-metadata, pyrsistent, jsonschema, mattermostwrapper, jsonpickle, python-socketio, redis, pydot, networkx, pycparser, cffi, cryptography, python-telegram-bot, psycopg2-binary, async-generator, python-crfsuite, tabulate, sklearn-crfsuite, rasa
Successfully installed PyJWT-1.7.1 PyYAML-5.3.1 SQLAlchemy-1.3.15 absl-py-0.9.0 aiofiles-0.4.0 aiohttp-3.6.2 apscheduler-3.6.3 astor-0.8.1 async-generator-1.10 async-timeout-3.0.1 attrs-19.3.0 boto3-1.12.30 botocore-1.15.30 cachetools-4.0.0 certifi-2019.11.28 cffi-1.14.0 chardet-3.0.4 cloudpickle-1.2.2 colorclass-2.2.0 coloredlogs-10.0 colorhash-1.0.2 cryptography-2.8 cycler-0.10.0 decorator-4.4.2 dnspython-1.16.0 docopt-0.6.2 docutils-0.15.2 fbmessenger-6.0.0 future-0.18.2 gast-0.2.2 gevent-1.4.0 google-auth-1.12.0 google-auth-oauthlib-0.4.1 google-pasta-0.2.0 greenlet-0.4.15 grpcio-1.27.2 h11-0.8.1 h2-3.2.0 h5py-2.10.0 hpack-3.0.0 hstspreload-2020.3.25 httplib2-0.17.0 httptools-0.1.1 httpx-0.9.3 humanfriendly-8.1 hyperframe-5.2.0 idna-2.9 importlib-metadata-1.5.2 jmespath-0.9.5 joblib-0.14.1 jsonpickle-1.3 jsonschema-3.2.0 kafka-python-1.4.7 keras-applications-1.0.8 keras-preprocessing-1.1.0 kiwisolver-1.1.0 markdown-3.2.1 matplotlib-3.1.3 mattermostwrapper-2.2 multidict-4.7.5 networkx-2.4 numpy-1.18.2 oauth2client-4.1.3 oauthlib-3.1.0 opt-einsum-3.2.0 packaging-19.0 pika-1.1.0 prompt-toolkit-2.0.10 protobuf-3.11.3 psycopg2-binary-2.8.4 pyasn1-0.4.8 pyasn1-modules-0.2.8 pycparser-2.20 pydot-1.4.1 pykwalify-1.7.0 pymongo-3.8.0 pyparsing-2.4.6 pyrsistent-0.16.0 pysocks-1.7.1 python-crfsuite-0.9.7 python-dateutil-2.8.1 python-engineio-3.11.2 python-socketio-4.4.0 python-telegram-bot-11.1.0 pytz-2019.3 questionary-1.5.1 rasa-1.9.2 rasa-sdk-1.9.0 redis-3.4.1 requests-2.23.0 requests-oauthlib-1.3.0 requests-toolbelt-0.9.1 rfc3986-1.3.2 rocketchat-API-0.6.36 rsa-4.0 ruamel.yaml-0.15.100 s3transfer-0.3.3 sanic-19.12.2 sanic-cors-0.10.0.post3 sanic-jwt-1.3.2 sanic-plugins-framework-0.9.2 scikit-learn-0.22.2.post1 scipy-1.4.1 six-1.14.0 sklearn-crfsuite-0.3.6 slackclient-2.5.0 sniffio-1.1.0 tabulate-0.8.7 tensorboard-2.1.1 tensorflow-2.1.0 tensorflow-addons-0.8.3 tensorflow-estimator-2.1.0 tensorflow-hub-0.7.0 tensorflow-probability-0.7.0 termcolor-1.1.0 terminaltables-3.1.0 tqdm-4.31.1 twilio-6.26.3 typeguard-2.7.1 tzlocal-2.0.0 ujson-1.35 urllib3-1.25.8 uvloop-0.14.0 wcwidth-0.1.9 webexteamssdk-1.1.1 websockets-8.1 werkzeug-1.0.0 wrapt-1.12.1 yarl-1.4.2 zipp-3.1.0
root@c02085da1f5f:/#

インストールできた。

次はrasaのinit。

の前に、作業ディレクトリを移動する。/ 直下でなんかファイルができると気持ち悪いので。

root@c02085da1f5f:/# pwd
/
root@c02085da1f5f:/# ls -al
total 88
drwxr-xr-x   1 root root 4096 Mar 27 08:25 .
drwxr-xr-x   1 root root 4096 Mar 27 08:25 ..
-rwxr-xr-x   1 root root    0 Mar 27 08:25 .dockerenv
drwxr-xr-x   4 root root  128 Mar 27 08:22 app
drwxr-xr-x   1 root root 4096 Mar 27 08:33 bin
drwxr-xr-x   2 root root 4096 Feb  1 17:09 boot
drwxr-xr-x   5 root root  360 Mar 27 08:25 dev
drwxr-xr-x   1 root root 4096 Mar 27 08:33 etc
drwxr-xr-x   2 root root 4096 Feb  1 17:09 home
drwxr-xr-x   1 root root 4096 Mar 27 08:33 lib
drwxr-xr-x   2 root root 4096 Feb 24 00:00 lib64
drwxr-xr-x   2 root root 4096 Feb 24 00:00 media
drwxr-xr-x   2 root root 4096 Feb 24 00:00 mnt
drwxr-xr-x   2 root root 4096 Feb 24 00:00 opt
dr-xr-xr-x 228 root root    0 Mar 27 08:25 proc
drwx------   1 root root 4096 Mar 27 08:27 root
drwxr-xr-x   3 root root 4096 Feb 24 00:00 run
drwxr-xr-x   2 root root 4096 Feb 24 00:00 sbin
drwxr-xr-x   2 root root 4096 Feb 24 00:00 srv
dr-xr-xr-x  13 root root    0 Mar 27 08:25 sys
drwxrwxrwt   1 root root 4096 Mar 27 08:36 tmp
drwxr-xr-x   1 root root 4096 Feb 24 00:00 usr
drwxr-xr-x   1 root root 4096 Feb 24 00:00 var
root@c02085da1f5f:/# cd app/
root@c02085da1f5f:/app# ls -al
total 12
drwxr-xr-x 4 root root  128 Mar 27 08:22 .
drwxr-xr-x 1 root root 4096 Mar 27 08:25 ..
-rw-r--r-- 1 root root   29 Mar 27 08:20 Dockerfile
-rw-r--r-- 1 root root  112 Mar 27 08:22 docker-compose.yml
root@c02085da1f5f:/app#

/app で作業する。

rasa init する

root@c02085da1f5f:/app# rasa init --no-prompt
Welcome to Rasa! ?

To get started quickly, an initial project will be created.
If you need some help, check out the documentation at https://rasa.com/docs/rasa.

Created project directory at '/app'.
Finished creating project structure.
Training an initial model...
Training Core model...

(なんやかんや)

2020-03-27 08:46:25 INFO     rasa.nlu.model  - Successfully saved model into '/tmp/tmp4p2k58s6/nlu'
NLU model training completed.
Your Rasa model is trained and saved at '/app/models/20200327-084527.tar.gz'.
If you want to speak to the assistant, run 'rasa shell' at any time inside the project directory.
root@c02085da1f5f:/app#

init できたっぽい。

ディレクトリ内を見てみる。

root@c02085da1f5f:/app# ls -al
total 32
drwxr-xr-x 14 root root  448 Mar 27 08:46 .
drwxr-xr-x  1 root root 4096 Mar 27 08:25 ..
-rw-r--r--  1 root root   29 Mar 27 08:20 Dockerfile
-rw-r--r--  1 root root    0 Mar 27 08:36 __init__.py
drwxr-xr-x  4 root root  128 Mar 27 08:45 __pycache__
-rw-r--r--  1 root root  757 Mar 27 08:36 actions.py
-rw-r--r--  1 root root  622 Mar 27 08:36 config.yml
-rw-r--r--  1 root root  938 Mar 27 08:36 credentials.yml
drwxr-xr-x  4 root root  128 Mar 27 08:45 data
-rw-r--r--  1 root root  112 Mar 27 08:22 docker-compose.yml
-rw-r--r--  1 root root  549 Mar 27 08:36 domain.yml
-rw-r--r--  1 root root 1456 Mar 27 08:36 endpoints.yml
drwxr-xr-x  3 root root   96 Mar 27 08:46 models
drwxr-xr-x  3 root root   96 Mar 27 08:45 tests
root@c02085da1f5f:/app#

なんか色々増えてる。

参考にした記事と同様に、まずは会話してみる。

root@c02085da1f5f:/app# rasa shell
2020-03-27 08:54:07 INFO     root  - Connecting to channel 'cmdline' which was specified by the '--connector' argument. Any other channels will be ignored. To connect to all given channels, omit the '--connector' argument.
2020-03-27 08:54:07 INFO     root  - Starting Rasa server on http://localhost:5005
2020-03-27 08:54:08.593814: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
Bot loaded. Type a message and press enter (use '/stop' to exit):
Your input ->  hello
Hey! How are you?
Your input ->  /stop
2020-03-27 08:54:31 INFO     root  - Killing Sanic server now.
root@c02085da1f5f:/app#

おお。できてる。

日本語に対応する

https://tech.mof-mof.co.jp/blog/rasa-nlu-japanese.html

次にこの記事に戻って日本語対応してみる。

まずは data/nlu.md の一番下にデータを追加してみる。

$ vi data/nlu.md 
data/nlu.md
## intent:restaurant_ja
- 渋谷で美味しいイタリアンない?
- 和食食べたいんだけど、六本木におすすめある?
- 今度麻布行くんだけど、フレンチのお店教えて

上記記事だとmecabをやめてspaCyを使っているようなので、mecabを飛ばしてspaCyでやってみる。

config.yml にデフォルト設定があるようなので、一旦全部消して以下を書いてみる。

config.yml
pipeline:
  # - name: “tokenizer_whitespace”
  - name: “nlp_spacy”
  - name: “tokenizer_spacy”
  - name: “CRFEntityExtractor”
  - name: “ner_crf”
  - name: “ner_synonyms”
  - name: “intent_featurizer_count_vectors”
  - name: “intent_classifier_tensorflow_embedding”

学習させてみる。

root@c02085da1f5f:/app# rasa train nlu
The config file 'config.yml' is missing mandatory parameters: 'language'. Add missing parameters to config file and try again.
root@c02085da1f5f:/app#

config.yml に languageが無いよって。

上記記事だとja_ginzaにしているようなので、端折って config.yml の一番上に ja_ginza を追加してみる。

config.yml
language: ja_ginza

もういっかいコマンドを叩いてみる。

root@c02085da1f5f:/app# rasa train nlu
Training NLU model...
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/registry.py", line 173, in get_component_class
    return class_from_module_path(component_name)
  File "/usr/local/lib/python3.7/site-packages/rasa/utils/common.py", line 211, in class_from_module_path
    raise ImportError(f"Cannot retrieve class from path {module_path}.")
ImportError: Cannot retrieve class from path “nlp_spacy”.

(なんやかんや)

nlp_spacyが云々で怒られている。

spaCy入れてないもんね。

spaCy入れてみる。

root@c02085da1f5f:/app# pip install spacy

(なんやかんや)

Successfully installed blis-0.4.1 catalogue-1.0.0 cymem-2.0.3 murmurhash-1.0.2 plac-1.1.3 preshed-3.0.2 spacy-2.2.4 srsly-1.0.2 thinc-7.4.0 tqdm-4.43.0 wasabi-0.6.0
root@c02085da1f5f:/app#

入った。

GiNZAの日本語処理ライブラリ?があるようなので、インストールする。

root@c02085da1f5f:/app# pip install "https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz"
Collecting https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz

(なんやかんや)

Successfully built ginza ja-ginza SudachiDict-core
Installing collected packages: ja-ginza, sortedcontainers, Cython, dartsclone, SudachiPy, SudachiDict-core, ginza
Successfully installed Cython-0.29.16 SudachiDict-core-20190927 SudachiPy-0.4.3 dartsclone-0.9.0 ginza-2.2.1 ja-ginza-2.2.0 sortedcontainers-2.1.0
root@c02085da1f5f:/app#

インストールできた。

これで準備できたか?

もう一回コマンドを叩く。

root@c02085da1f5f:/app# rasa train nlu
Training NLU model...
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/registry.py", line 173, in get_component_class
    return class_from_module_path(component_name)
  File "/usr/local/lib/python3.7/site-packages/rasa/utils/common.py", line 211, in class_from_module_path
    raise ImportError(f"Cannot retrieve class from path {module_path}.")
ImportError: Cannot retrieve class from path “nlp_spacy”.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/rasa", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.7/site-packages/rasa/__main__.py", line 91, in main
    cmdline_arguments.func(cmdline_arguments)
  File "/usr/local/lib/python3.7/site-packages/rasa/cli/train.py", line 140, in train_nlu
    persist_nlu_training_data=args.persist_nlu_data,
  File "/usr/local/lib/python3.7/site-packages/rasa/train.py", line 414, in train_nlu
    persist_nlu_training_data,
  File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
  File "/usr/local/lib/python3.7/site-packages/rasa/train.py", line 445, in _train_nlu_async
    persist_nlu_training_data=persist_nlu_training_data,
  File "/usr/local/lib/python3.7/site-packages/rasa/train.py", line 474, in _train_nlu_with_validated_data
    persist_nlu_training_data=persist_nlu_training_data,
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/train.py", line 74, in train
    trainer = Trainer(nlu_config, component_builder)
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/model.py", line 142, in __init__
    components.validate_requirements(cfg.component_names)
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/components.py", line 51, in validate_requirements
    component_class = registry.get_component_class(component_name)
  File "/usr/local/lib/python3.7/site-packages/rasa/nlu/registry.py", line 199, in get_component_class
    raise ModuleNotFoundError(exception_message)
ModuleNotFoundError: Cannot find class '“nlp_spacy”' from global namespace. Please check that there is no typo in the class name and that you have imported the class into the global namespace.
root@c02085da1f5f:/app#

なんか怒られた。

Cannot find class '“nlp_spacy”' ってなんだろ。

ModuleNotFoundError: Cannot find class '“nlp_spacy”' from global namespace. Please check that there is no typo in the class name and that you have imported the class into the global namespace. でググってみる。

https://github.com/RasaHQ/rasa/blob/master/rasa/nlu/registry.py

このページが一番上に出てきた。

https://github.com/RasaHQ/rasa/blob/master/rasa/nlu/registry.py#L101

old_style_names

"nlp_spacy": "SpacyNLP",

こんな感じの対応付けが定義されている。

さっきconfig.ymlに書いたのが、nlp_spacy だから SpacyNLP に変更してみる。

config.yml
language: ja_ginza

pipeline:
  # - name: “tokenizer_whitespace”
  - name: "SpacyNLP" # ←ここを変更
  - name: "tokenizer_spacy"
  - name: "CRFEntityExtractor"
  - name: "ner_crf"
  - name: "ner_synonyms"
  - name: "intent_featurizer_count_vectors"
  - name: "intent_classifier_tensorflow_embedding"

再度コマンドを叩く。

root@c02085da1f5f:/app# rasa train nlu
Training NLU model...

(なんやかんや)

ModuleNotFoundError: Cannot find class '“SpacyNLP”' from global namespace. Please check that there is no typo in the class name and that you have imported the class into the global namespace.

“SpacyNLP” ??

あ、コピペしたらダブルクオートがおかしいのか。

ダブルクオートを治す。

config.yml
language: ja_ginza

pipeline:
  # - name: “tokenizer_whitespace”
  - name: "nlp_spacy"
  - name: "tokenizer_spacy"
  - name: "CRFEntityExtractor"
  - name: "ner_crf"
  - name: "ner_synonyms"
  - name: "intent_featurizer_count_vectors"
  - name: "intent_classifier_tensorflow_embedding"

もういっかいコマンド叩く。

root@c02085da1f5f:/app# rasa train nlu
Training NLU model...

(なんやかんや)

oblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
  warnings.warn(msg, category=FutureWarning)
2020-03-27 09:15:20 INFO     rasa.nlu.model  - Successfully saved model into '/tmp/tmpn4xtb3h7/nlu'
NLU model training completed.
Your Rasa model is trained and saved at '/app/models/nlu-20200327-091520.tar.gz'.
root@c02085da1f5f:/app#

お、やっと動いた。

rasa shell nlu で intent が取れれば成功?

root@c02085da1f5f:/app# rasa shell nlu
2020-03-27 09:16:26 INFO     rasa.nlu.components  - Added 'SpacyNLP' to component cache. Key 'SpacyNLP-ja_ginza'.
/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/__init__.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
  warnings.warn(msg, category=FutureWarning)
2020-03-27 09:16:26.359929: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
/usr/local/lib/python3.7/site-packages/rasa/nlu/classifiers/diet_classifier.py:864: FutureWarning: 'EmbeddingIntentClassifier' is deprecated and will be removed in version 2.0. Use 'DIETClassifier' instead.
  model=model,
NLU model loaded. Type a message and press enter to parse it.
Next message:
六本木のイタリアン教えて
{
  "intent": {
    "name": "restaurant_ja",
    "confidence": 0.48260971903800964
  },
  "entities": [],
  "intent_ranking": [
    {
      "name": "restaurant_ja",
      "confidence": 0.48260971903800964
    },
    {
      "name": "affirm",
      "confidence": 0.1126396581530571
    },
    {
      "name": "greet",
      "confidence": 0.09804855287075043
    },
    {
      "name": "goodbye",
      "confidence": 0.08541827648878098
    },
    {
      "name": "mood_great",
      "confidence": 0.07586738467216492
    },
    {
      "name": "deny",
      "confidence": 0.06578702479600906
    },
    {
      "name": "bot_challenge",
      "confidence": 0.05436018109321594
    },
    {
      "name": "mood_unhappy",
      "confidence": 0.025269268080592155
    }
  ],
  "text": "六本木のイタリアン教えて"
}
Next message:

お、それっぽい。intentのスコア低いけど、こんなもん?

固有表現もやってみよう。

data/nlu.md の日本語の箇所を下記のように書き換えて、

data/nlu.md
## intent:restaurant_ja
- [渋谷](location)で美味しい[イタリアン](restaurant_type)ない?
- [和食](restaurant_type)食べたいんだけど、[六本木](location)におすすめある?
- 今度[麻布](location)行くんだけど、[フレンチ](restaurant_type)のお店教えて

学習させて、

root@c02085da1f5f:/app# rasa train nlu
Training NLU model...

(なんやかんや)

2020-03-27 13:46:37 INFO     rasa.nlu.model  - Finished training component.
/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/__init__.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
  warnings.warn(msg, category=FutureWarning)
2020-03-27 13:46:37 INFO     rasa.nlu.model  - Successfully saved model into '/tmp/tmpy7tqyrsb/nlu'
NLU model training completed.
Your Rasa model is trained and saved at '/app/models/nlu-20200327-134637.tar.gz'.
root@c02085da1f5f:/app#

shell を叩いてみる。

root@c02085da1f5f:/app# rasa shell nlu
2020-03-27 13:47:07 INFO     rasa.nlu.components  - Added 'SpacyNLP' to component cache. Key 'SpacyNLP-ja_ginza'.
/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/__init__.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
  warnings.warn(msg, category=FutureWarning)
2020-03-27 13:47:07.924760: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
/usr/local/lib/python3.7/site-packages/rasa/nlu/classifiers/diet_classifier.py:864: FutureWarning: 'EmbeddingIntentClassifier' is deprecated and will be removed in version 2.0. Use 'DIETClassifier' instead.
  model=model,
NLU model loaded. Type a message and press enter to parse it.
Next message:
渋谷で美味しいイタリアンない?
{
  "intent": {
    "name": "restaurant_ja",
    "confidence": 0.9823814034461975
  },
  "entities": [
    {
      "start": 0,
      "end": 2,
      "value": "渋谷",
      "entity": "location",
      "confidence": 0.7429793877231764,
      "extractor": "CRFEntityExtractor"
    },
    {
      "start": 7,
      "end": 12,
      "value": "イタリアン",
      "entity": "restaurant_type",
      "confidence": 0.7588623133724827,
      "extractor": "CRFEntityExtractor"
    },
    {
      "start": 0,
      "end": 2,
      "value": "渋谷",
      "entity": "location",
      "confidence": 0.7429793877231764,
      "extractor": "CRFEntityExtractor"
    },
    {
      "start": 7,
      "end": 12,
      "value": "イタリアン",
      "entity": "restaurant_type",
      "confidence": 0.7588623133724827,
      "extractor": "CRFEntityExtractor"
    }
  ],
  "intent_ranking": [
    {
      "name": "restaurant_ja",
      "confidence": 0.9823814034461975
    },
    {
      "name": "mood_great",
      "confidence": 0.008284788578748703
    },
    {
      "name": "deny",
      "confidence": 0.006644146051257849
    },
    {
      "name": "greet",
      "confidence": 0.001571052591316402
    },
    {
      "name": "bot_challenge",
      "confidence": 0.0006475948612205684
    },
    {
      "name": "affirm",
      "confidence": 0.00034828390926122665
    },
    {
      "name": "mood_unhappy",
      "confidence": 8.46567636472173e-05
    },
    {
      "name": "goodbye",
      "confidence": 3.805106462095864e-05
    }
  ],
  "text": "渋谷で美味しいイタリアンない?"
}
Next message:

おお。記事みたいな出力になった。

記事とは違って日本語は文字化けしてないけど。

環境ができて動くところまで見れたので、今回はここまで。
今後は教師データを増やす方法を考える。

追記

ここまでの成果として、pip で install したライブラリを requirements.txt にして、build したら勝手にインストールされるように Dockerfile に処理を追記しておいた。

requirements.txt
rasa==1.9.2
spacy==2.2.4
FROM python:3.7-slim-stretch

RUN apt-get update -q -y && \
    apt-get install -q -y \
    build-essential

ADD ./requirements.txt requirements.txt

RUN pip install -r requirements.txt
RUN pip install "https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz"

ADD . /app
WORKDIR /app

んで、build して

$ docker-compose build

動かす

$ docker-compose run --rm rasa bash
root@56ff2c2f2f38:/app#

追記2

github で公開した

https://github.com/booink/rasa-trial

追記3

ginzaのインストールはpip経由で(3.0から)できるようになったようなので、requirements.txtにginzaを追記してDockerfileから該当箇所を削除した。

https://github.com/booink/rasa-trial/commit/eb8e020d70ad8d92e29c628008d550d214bcc14c

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

[docker] docker pull が途中で止まる時は "max-concurrent-downloads 1" を試してみよう

概要

遅いインターネット回線で "docker pull" してたら途中で止まってしまった。
Dockerの設定を変更して最大同時ダウンロード数(max-concurrent-downloads)を"1"にしたらうまくいった。

環境

Host OS: Windows 10 Home
- "Docker Toolbox" でDockerを利用

Docker: version 19.03.1

$ docker --version
Docker version 19.03.1, build 74b1e89e8a

背景

自宅PCでDockerを使っていたが、ある事情で家のインターネット回線を解約しました。
仕方なく、格安SIM(楽天モバイル)のテザリングでネットに繋いでいるので回線が重い。

すると、(今までそんなことなかったのに) docker build 等のコマンドでネットからファイル取得中に進まなくなる現象が多発するようになりました。

現象

例えば以下のような感じで、ファイルのダウンロード中で止まってしまう。

$ docker pull php:7.4-fpm-alpine
7.4-fpm-alpine: Pulling from library/php
aad63a933944: Downloading [==========================>                        ]   1.51MB/2.803MB
b61c449d5d91: Download complete
3fde16e1397a: Download complete
b1096698ab2a: Download complete
1b7b3153bac8: Download complete
c25256547bec: Download complete
47e7fc912cc2: Download complete
7ad4a4e5e343: Download complete
1739f6256835: Download complete
40c44c56af3f: Download complete

いくら待っても、これ以上進まない。
数回試したが、止まるファイルやどこまで進んだかが一定ではない。

解決策

色々調べると "Docker daemon" の起動時オプションで以下を追加するとうまくいきそう。

--max-concurrent-downloads 1

("max-concurrent-downloads" オプションについては https://docs.docker.com/engine/reference/commandline/dockerd/ 参照)

Docker toolbox を使っている場合は、以下の手順で変更できるようだ。

docker-machineに接続

$ docker-machine ssh default

profileファイル編集

[docker@default]
docker@default: sudo vi /var/lib/boot2docker/profile
  # EXTRA_ARGS に "--max-concurrent-downloads 1" を追加する
docker@default: cat /var/lib/boot2docker/profile

EXTRA_ARGS='
--label provider=virtualbox
--max-concurrent-downloads 1
'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=overlay2
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem

docker@default: exit

docker-machine再起動

docker-machine restart default

(https://github.com/boot2docker/boot2docker#docker-daemon-options 参照)

結果

上記設定変更作業すると以下のようになった。

  • pull するファイルが3並列だったのが直列になった。
  • 途中で止まらなくなった。

まとめ

ネット接続が重い状態で docker pull が止まる場合、並列ダウンロードを止めると改善する場合がある。

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

vagrantとDockerで環境構築をした

はじめに

Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説を参考に環境構築をしたときにエラーとなったことをまとめて書いていきます。

VirtualBoxをインストールから、Mutagenのインストール・セットアップまでは問題なくできたので、その次のコマンドから書いていきます。

Vagrantを起動

コマンド実行後に、エラーが発生しました。

$ vagrant up
/Users/hoge/.vagrant.d/gems/2.4.9/gems/vagrant-mutagen-0.1.2/lib/vagrant-mutagen/Mutagen.rb:22:in `initialize': No such file or directory @ rb_sysopen - /Users/hoge/.ssh/config (Errno::ENOENT)

configが無いと言われているので、作ってあげます。
ディレクトリ名かと思ってたらファイル名でした

$ touch /Users/hoge/.ssh/config

再度、upすると今度は成功するはずです。

$ vagrant up

仮想環境にSSH接続

接続はすんなりできました。

$ vagrant ssh
root@087fc4a682c3:/ cd app
root@087fc4a682c3:/app# docker-compose -f docker-compose.dev.yml build
root@087fc4a682c3:/app# docker-compose -f docker-compose.dev.yml up

# dockerにログインしてないとエラーが出たらログインしましょう
root@087fc4a682c3:/app# docker login

さいごに

Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説は初心者の私にとってわかりやすかったです。
さらなるエラー箇所については、解決したら追記していきます。

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

Docker 個人的まとめ

docker run [OPTIONS] IMAGE [COMMANDS]

docker run -it -d IMAGE
-it:入力&ターミナル表示
-d:バックグラウンド

docker pull [image]
imageをダウンロード

docker ps
動いているcontainerを表示

docker ps -a
全てのcontainerを表示

docker stop [ID or tag]
containerを止める

docker rm [container]
containerを削除

docker rmi [ID or tag]
imageを削除

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

Amazon Linux2でDockerをインストールする方法が2種類ある

amazon-linux-extrasでインストールすると18.09.9-ceがインストールされる(2020/3/27現在)
yumでインストールすると19.03.6-ceがインストールされた(2020/3/27現在)

amazon-linux-extrasの場合のインストール方法

$ sudo amazon-linux-extras install -y docker

$ docker -v

Docker version 18.09.9-ce, build 039a7df

yumの場合のインストール方法

$ sudo yum install -y docker

$ docker -v

Docker version 19.03.6-ce, build 369ce74
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VirtualBoxにAlpineをいれてdocker redmine

VirualBox

install

Alpine

VIRTUALをいれた

Docker

apk update
apk upgrade
apk add nano
nano /etc/apk/repositories
(community, testingを有効にする)
apk add docker docker-compose

sshのroot loginを有効にする

nano /etc/ssh/sshd_config

PermitRootLogin yes
を追加

/etc/init.d/sshd restart

docker redmine

ここに沿って進める

ssh -l root 192.168.xxx.xxx

mkdir /var/www/redmine
...

redmineのplugin

参考

cd /var/www/redmine/plugins
必要なpluginをダウンロードして展開

以下を実行

docker exec redmine bundle install --jobs=4 --without development test && \
docker exec redmine bundle exec rake redmine:plugins:migrate RAILS_ENV=production && \
docker exec redmine passenger-config restart-app /usr/src/redmine

work time

https://github.com/tkusukawa/redmine_work_time

absolute date

https://github.com/suer/redmine_absolute_dates

issue badge

https://www.redmine.org/plugins/redmine_issue_badge

Redmine 3.x

clipboard_image_paste

https://www.redmine.org/plugins/clipboard_image_paste

Question

リンク
チケットでやったほうがワークフロー、ステータスが管理できて良い。

Isuue Template

リンク
redmine 3.xには0.2.xを持ってこないとだめ
redmine 3.x用
また、フォルダ名は"redmine_issue_templates"にする必要がある

いい感じである

※ロールと権限でテンプレートの表示を有効にすること
templateを利用してのチケット作成がシステム管理者でしかできない?

 

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

ポートフォリオ公開

学習期間3ヶ月の初学者がポートフォリオを公開してみる。

なぜ書いたか?

ふとダウンロードしたアプリによって余命を知りこのままではまずいと焦った。(現在28歳あと51年の余命だそうです。)
余命タイマー

AWSの漫画を読んでいたところ「アウトプットしないのは知的な便秘」という話から便秘は嫌だなーと思いたち急遽この記事を書いております。

最初の記事で何を書こうか迷ったのですが、いきなりすごい記事は書けないので、プログラミングスクールに3ヶ月通い、そこで得た知見と自己学習の成果を発表することで、今からプログラミングを学び始める方の参考になればいいなと思い書かせていただきます。

自己紹介

初めまして。いつもQiitaの記事にはお世話になっております。私の経歴からお話しさせていただくと、もともと消防士を4年ほどしていまして、今はエンジニア転職を目指す28歳です。
元々コンピューターには疎く仕事でもそれほどパソコンは触らないので、タッチタイピングもできない状態でmac?何それ美味しいの?あーポテト食べたくなってきた。からのスタートでした。
本格的にプログラミングを学び始めたのは2019年の12月からです。これから発信活動もしていけたらと思っています!

はじめに

いきなりですがポートフォリオを実際に見てもらった方が早いと思うので一部公開します。
またプログラミングにこれから触れる方向けに記事を書いておりますので用語の説明をなるべく噛み砕いてさせていただいてます。つよつよエンジニアのみなさん、間違っているところありましたらコメントしていただけると幸いです。

概要

メンターマッチングサイトMENTAのクローン(模倣)サイトです。

開発環境

  • Docker 19.03.5 (コンテナという技術を用いてアプリを立ち上げるための環境構築が楽になる)
  • CircleCI 2.0 (自動でテストを行う。githubというサービスを用いてインターネットに自分のソースコードをあげたときに自動的にテストを行う仕組み)
  • Ruby on Rails 5.2.4.1 (Rubyをもちいてアプリを簡単に作れるようにしたもの。フレームワークと呼ばれる)
  • Ruby 2.5.1 (日本人のまつもとさんが作った偉大なプログラミング言語)
  • MySQL 5.6 (データベース、いろいろなデータが入っているエクセルみたいなもの)
  • unicorn 5.4.1 (アプリケーションサーバー、動きがある画面を返すパソコンみたいなもの)
  • nginx 1.16.1 (webサーバー、文字だけなど静的な画面を返すパソコンみたいなもの)

環境仕様

  • Dockerによる開発環境構築
  • CircleCIによる自動テスト(rubocop,siderによる自動コードレビュー、ソースコードを綺麗にしてくれるもの)
  • CapistranoによるAWSへの自動デプロイ (デプロイ・・・インターネットに自分のサイトを公開すること、AWS・・・アマゾンがやっているサーバーのサービス)

アプリケーション仕様

  • ユーザーサインイン・ログイン機能
  • ユーザー編集、削除(退会)機能
  • プラン投稿、編集、削除機能
  • メッセージ送受信機能、返信機能
  • ユーザーフォロー機能
  • タグ機能
  • 記事投稿、編集、削除機能
  • メンター検索機能、タグ検索機能

制作期間 

3週間から1ヶ月

DEMO

  • TOPページ
    screencapture-18-178-33-110-2020-03-27-11_45_19

  • メインページ
    screencapture-18-178-33-110-users-2020-03-27-11_47_18

  • プラン作成画面
    screencapture-localhost-3000-plans-new-2020-03-22-23_00_51

  • メンター一覧画面
    screencapture-18-178-33-110-plans-new-arrival-mentor-2020-03-27-11_49_02

  • メンタースキル絞り込み画面
    screencapture-18-178-33-110-plans-search-2020-03-27-11_50_31

  • プラン詳細画面
    screencapture-18-178-33-110-plans-22-2020-03-25-15_44_53

  • プロフィール画面
    screencapture-18-178-33-110-users-31-2020-03-25-15_38_31

  • 退会確認画面
    screencapture-localhost-3000-users-1-delete-confirm-2020-03-22-23_06_25

やったこと

  • 3ヶ月間、毎日10時間はパソコンの画面を見つめました。(おかげで視力が悪くなったかも笑)
  • スクールの友人とアウトプットをする(説明できないことは理解が足りていない)
  • ひたすらググる。(ただググるだけではなく仮説を立ててからググる)

こうすればよかったこと

コピペは辞める。(理解してコピペならいいが思考停止でコピペは本当によくない。)

アプリを作ってみて

  • 筋トレと一緒で頭を悩ましている(脳みそに負荷をかけている)時が一番成長している気がする。
  • 最初は辛いけど徐々にできることが増えていき楽しくなってくる...はず笑
  • あるあるだと思いますが、プログラミングを知らない人にアプリを見せてもあまり興味を持ってくれない:joy:(家族に見せてもへーくらいの感想しかもらえない。でもそれが本当のユーザーの反応なのである笑)
  • まだまだ全然完成してないんですが、就活始めなきゃということで僕の実力ではここまででした。
3ヶ月間毎日少しずつでも学習すれば優秀なみなさんならもっといいものが作れると思います。これからプログラミングを始める方の参考になれば幸いです。
最後までみていただきありがとうございます!
もしソースコードを公開してほしいというリクエストがありましたらコメントよろしくお願いします!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

学習期間3ヶ月の初学者がポートフォリオを公開してみる。

なぜ書いたか?

いつもと変わらぬ1日が始まり、なんとなしに携帯をいじっていると余命診断アプリなるものを見つけました。面白そうだなと思い、ダウンロードして余命を診断してみるとなんとあと51年しか生きられないというではありませんか。
人によってはあと51年もあると考えるのかもしれませんが、なんとなくあと70年くらいは生きられるとのほほんと考えていた私にとってこの51年というのはあまりに少ない。何か後世に残さなければということで筆を...じゃなくてキーボードを叩いているところでございます。
余命タイマー

また個人的にAWSの勉強をし始めたのですが、とっかかりにAWSの漫画を読んでいたところ「アウトプットしないのは知的な便秘」というフレーズから便秘は嫌だなーと思い急遽この記事を書いております。

最初の記事で何を書こうか迷ったのですが、いきなりすごい記事は書けないので、プログラミングスクールに3ヶ月通い、そこで得た知見と自己学習の成果を発表することで、今からプログラミングを学び始める方の参考になればいいなと思い書かせていただきます。

自己紹介

初めまして。いつもQiitaの記事にはお世話になっております。私の経歴からお話しさせていただくと、もともと消防士を4年ほどしていまして、今はエンジニア転職を目指す28歳です。
元々コンピューターには疎く仕事でもそれほどパソコンは触らないので、タッチタイピングもできない状態でmac?何それ美味しいの?あーポテト食べたくなってきた。という状態からのスタートでした。
本格的にプログラミングを学び始めたのは2019年の12月からです。これから様々なことにチャレンジしていけたらと思っています!
最近はひたすらプログラミングと英語に明け暮れる毎日です。

はじめに

さっそくですがポートフォリオを実際に見てもらった方が早いと思うのでここに公開します。
またプログラミングにこれから触れる方向けに記事を書いておりますので用語の説明をなるべく噛み砕いてさせていただいてます。つよつよエンジニアのみなさん、間違っているところやお気づきの点がありましたらコメントしていただけるととても嬉しいです。
(就活中なのでサイトとgithubを公開するか迷ったんですが、つよつよエンジニアの方のアドバイスがもらえるかもしれないと考えたら機会損失になるのはもったいないと思い公開しました:sunglasses:

アプリタイトル

first_skill_app

URL

https://firstskillapp.com/

github

https://github.com/gangelion/first_skill_app

概要

メンターマッチングサイトMENTAのクローンサイトです。
https://menta.work/

テストアカウント

  • BASIC認証
    • ユーザー名 : 1111
    • パスワード : 1111
  • メールアドレス : test@1
  • パスワード : 11111111
    • 万が一テストユーザーが消えている場合はメールアドレスtest@*でログインできます。(*に数字を入れてください)

開発環境

  • Docker 19.03.5 (コンテナという技術を用いてアプリを立ち上げるための環境構築が楽になる)
  • CircleCI 2.0 (自動でテストを行う。githubというサービスを用いてインターネットに自分のソースコードをあげたときに自動的にテストを行う仕組み)
  • Ruby on Rails 5.2.4.1 (Rubyをもちいてアプリを簡単に作れるようにしたもの。フレームワークと呼ばれる)
  • Ruby 2.5.1 (日本人のまつもとさんが作った偉大なプログラミング言語)
  • MySQL 5.6 (データベース、いろいろなデータが入っているエクセルみたいなもの)
  • unicorn 5.4.1 (アプリケーションサーバー、動きがある画面を返すパソコンみたいなもの)
  • nginx 1.16.1 (webサーバー、文字だけなど静的な画面を返すパソコンみたいなもの)

環境仕様

  • Dockerによる開発環境構築
  • CircleCIによる自動テスト(rubocop,siderによる自動コードレビュー・・・ソースコードを綺麗にしてくれるもの)
  • CapistranoによるAWSへの自動デプロイ (デプロイ・・・インターネットに自分のサイトを公開すること、AWS・・・アマゾンがやっているサーバーのサービス)
  • AWS(EC2,VPC,route53,Certificate Manager)(AWSの各種サービスです。)

アプリケーション仕様

  • ユーザーサインイン・ログイン機能
  • ユーザー編集、削除(退会)機能
  • プラン投稿、編集、削除機能
  • メッセージ送受信機能、返信機能
  • ユーザーフォロー機能
  • タグ機能
  • 記事投稿、編集、削除機能
  • メンター検索機能、タグ検索機能

制作期間 

3週間から1ヶ月

DEMO

  • TOPページ
    screencapture-18-178-33-110-2020-03-27-11_45_19

  • メインページ
    screencapture-18-178-33-110-users-2020-03-27-11_47_18

  • プラン作成画面
    screencapture-localhost-3000-plans-new-2020-03-22-23_00_51

  • メンター一覧画面
    screencapture-18-178-33-110-plans-new-arrival-mentor-2020-03-27-11_49_02

  • メンタースキル絞り込み画面
    screencapture-18-178-33-110-plans-search-2020-03-27-11_50_31

  • プラン詳細画面
    screencapture-18-178-33-110-plans-22-2020-03-25-15_44_53

  • プロフィール画面
    screencapture-18-178-33-110-users-31-2020-03-25-15_38_31

  • 退会確認画面
    screencapture-localhost-3000-users-1-delete-confirm-2020-03-22-23_06_25

やったこと

  • 3ヶ月間、毎日10時間はパソコンの画面を見つめました。(おかげで視力が悪くなったかも笑)
  • スクールの友人とアウトプットをする(説明できないことは理解が足りていない)
  • ひたすらググる。(ただググるだけではなく仮説を立ててからググる)

こうすればよかったこと

コピペは辞める。(理解してコピペならいいが思考停止でコピペは本当によくない。)

アプリを作ってみて

  • 筋トレと一緒で頭を悩ましている(脳みそに負荷をかけている)時が一番成長している気がする。
  • 最初は辛いけど徐々にできることが増えていき楽しくなってくる...はず笑
  • あるあるだと思いますが、プログラミングを知らない人にアプリを見せてもあまり興味を持ってくれない:joy:(家族に見せてもへーくらいの感想しかもらえない。でもそれが本当のユーザーの反応なのである笑)
  • まだまだ全然完成してないんですが、就活始めなきゃということで僕の実力ではここまででした。(これからも修正やアップデートはしていくつもりです。)
3ヶ月間毎日少しずつでも学習すれば優秀なみなさんならもっといいものが作れると思います。これからプログラミングを始める方の参考になれば幸いです。
最後までみていただきありがとうございます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Veritas Flexアプライアンスのリソース管理

はじめに

 本稿ではVeritas Flexアプライアンスの動的なリソース割り当ての仕組みとそのリソース割り当て状況の確認手法について解説したいと思います。Veritas FlexアプライアンスはDockerコンテナ上にアサインされたNetBackupアプライアンスです。以前の記事でFlexアプライアンスについて記載していますのでこちらの記事もご参照ください。

Veritas Flexアプライアンスのリソースマネージメントの仕組み

 Flexソフトウェアが導入されていない通常のNetBackupの場合、初期設定時にNetBackupコンポーネント毎にCPU、メモリなどのリソースの割り当てを設定します。そのリソース割り当てが運用後の動作・パフォーマンス等に反映されることもあるため、サイジングにある一定の配慮が必要となります。
 一方、Veritas Flexアプライアンスの場合、初期設定等の管理者のオペレーションで各種インスタンス毎のリソース割り当ては不要となり、それぞれのコンテナが都度の状況に応じて必要なリソースを活用できるようにリソース配分を動的に自動実行します。つまり、それぞれのコンテナの負荷状況に応じて柔軟に使えるようにリソースを可変的にアロケートしているということになります。
 これにより負荷がいずれかのサーバインスタンスに偏ってサーバがハングしてしまう、動作が不安定になる、などの可能性を極小化し、ハードウェアやNetBackupが持つパフォーマンスを最大化できるようなアーキテクチャになっています。

image.png

では、各種インスタンス毎の割り当てリソースはどこで確認できるのか?

動的に割り当てられている、それぞれのリソースについてはFlexShellのパフォーマンスダッシュボードでインスタンス毎のリソース使用量を確認可能できます。

実際、各種インスタンス毎のリソース、パフォーマンス状況を確認してみましょう。

① Flex Appliance Shellへのアクセスしてログインします。
Flex Appliance ShellにアクセスするにはアプライアンスノードへSSHでアクセスし、以下ユーザ名とパスワードでログインします。

ユーザID: hostadmin
Password: 初期構成中に設定したパスワード
 ※初期構成をまだ完了していない場合は、デフォルトのパスワードはP@ssw0rdとなります。
 ※またマルチノードのFlexアプライアンスを使用している場合は、各ノードに個別にログインする必要があります。

② show instance performanceコマンドを入力します。
image.png

③ 各種リソース割り当て状況が表示されます。
image.png

④ [NAME]箇所のコンテナインスタンスを選択し、Enterを押下します。
image.png

⑤ single viewを選択します。
image.png

⑥ 選択した単一インスタンスのビューに切り替わります。
image.png

<参考>因みにFlexはDockerコンテナで構成されていますので、Dockerコマンドも利用できます。
sudo docker statsコマンドを入力します。
image.png

<参考>コンテナのCPU使用率とメモリ使用率を表示します。
image.png

まとめ

 Veritas FlexアプラインスはDockerコンテナの仮想環境の上に構築されたNetBackupであり、また動的にリソースを割り振りますので、各種コンポーネントにリソースをサイジングして、割り当て設定する必要がありません。また、アプライアンスであれば既に検証済みの構成でHWスペックが固定ですので、NetBackupにそれほど明るくないエンジニアの方でもサイジングに困ることがありません。加えて、Flexソフトウェアが負荷に応じてリソースを割り当てますので運用後にシステムトラブルやパフォーマンスに関する齟齬がおきにくくなります。
 バックアップの導入前のサイジングや運用に手間をかけたくない、という方はFlexアプライアンスの活用もご検討ください。

商談のご相談はこちら

本稿からのお問合せをご記入の際には「お問合せ内容」に#GWCのタグを必ずご記入ください。ご記入いただきました内容はベリタスのプライバシーポリシーに従って管理されます。

その他リンク

【まとめ記事】ベリタステクノロジーズ 全記事へのリンク集もよろしくお願いいたします。

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

Dockerを使ってMacホスト上でUbuntuのMavenビルドするまでの手順

諸事情あって、Ubuntu上でのMavenビルドを確認したくて、環境を作るため、初めてのDockerに手を出しました。その時の覚え書きです。
なお、私はUbuntuは触ってみたことがある程度で、あまり詳しくはありません。LPIC Level1は昔持ってたので(現在は期限切れ)、初歩的なコマンドはわかります。という程度です。

環境

ホスト側

ツールなど 環境
macOS Mojave 10.14.5
Docker 19.03.8

Dockerコンテナ側

ツールなど 環境
Ubuntu 18.0.4(Latest)
Apache Maven 3.6.3
JDK AdoptOpenJDK 11.0.6 2020-01-14

Dockerインストール

まずMacにDockerをインストールします。

1. Dockerアカウント作成

その前に、Dockerの公式サイトでアカウントを作成します。

https://www.docker.com/

2. Docker Desktop for Macをインストール

Docker Desktop for Macというアプリをインストールします。

https://hub.docker.com/editions/community/docker-ce-desktop-mac

インストール後、下記コマンドでバージョンが表示されればOK.

$ docker --version

UbuntuをDockerに構築

1. Ubuntuイメージをpull

$ docker pull ubuntu

pull出来たかは以下のコマンドで確認。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              4e5021d210f6        5 days ago          64.2MB

2. Ubuntuの起動とセットアップ

2.1 コンテナを起動

$ docker run -it -d --name ubuntuLatest ubuntu:latest

--nameのあとの名称は任意です。
ubuntu:latestは、docker imagesコマンドで表示された、{REPOSITORY}:{TAG}としています。
Ubuntuのイメージが1つしかなければ、{TAG}の部分は不要かも。

2.2 コンテナに入る/抜ける

$ docker exec -it ubuntuLatest /bin/bash

これでバッシュコマンドが打てる状態で繋がります。
抜けるときは、

$ exit

でOK.
もう一度入るときは、

$ docker exec -it ubuntuLatest bash

とする。

3. apt-getのアップデート

いろいろパッケージをインストールするのに必要なのでまずはこれから。やっておかないと何もインストールできませんでした。

$ apt-get update

また、add-apt-repositoryなどが動くように以下を実行して、再度apt-get updateしておく。

$ apt-get install -y software-properties-common
$ apt-get update

4. vimをインストール

なにかエディタ入れておかないと何も出来ないので、vimでも入れておきます。
お好みで良いでしょう。

$ apt-get install -y vim

5. SSHをインストール

Gitに繋ぐのに、SSH鍵が必要だったので、入れました。

$ apt-get install -y ssh

Ubuntuにビルド環境をセットアップ

1. AdaoptOpenJDK 11のインストール

$ add-apt-repository --yes ppa:rpardini/adoptopenjdk
$ apt-get update
$ apt-get install -y adoptopenjdk-11-installer

1行目のコマンドで、AdoptOpenJDKのリポジトリを追加しています。
リポジトリを追加したら、apt-get updateが必要みたいです。

JDKインストール後、java --versionとやって以下のように出ればOKです。

/# java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

2. Maven

$ apt-get install -y maven

インストール後に、mvn -vと打ってバージョンが表示されればOK。

3. Git

$ apt-get install -y git

インストール後に、git --versionと打ってバージョンが表示されればOK.
また、グローバルユーザー設定をしておく。

$ git config --global user.name [任意のユーザ名]
$ git config --global user.email [任意のメールアドレス]

4. Git接続用SSH鍵生成

$ cd ~
$ mkdir .ssh
$ cd .ssh
$ ssh-keygen -t rsa

あとは通常通りに設定を行う。

公開鍵の内容のコピーは、cat id_rsa.pubとやってコピーすれば良い。
Gitへの公開鍵の登録をお忘れなく。

Githubの場合、以下で接続確認ができる。

$ ssh -T git@github.com

yesと打つのを忘れずに。

5. Gitからクローンしてビルド

任意のフォルダを作ってそこに移動してから、

$ git clone [SSH用のリポジトリURL]

Githubなどから、SSH用のURLをコピーしてくるのを間違えないように。

クローンしてきたらプロジェクトフォルダに移動してから、任意のブランチをチェックアウト。

$ cd [project dir name]
$ git checkout -b branch_name origin/branch_name

ビルド実行。

$ mvn install

おめでとうございます。
Dockerコンテナ内のUbuntuでmavenビルドが出来るようになりました。

ステップ数は長いけど、結構単純なことの繰り返しなので、それほど難しくないように思います。
でも、どこかに、Mavenビルド用のイメージはいろいろ転がっていそうですよね(汗)

これを社内で共有しようと思ったら、Dockerリポジトリに公開すればいいのかしら??

その他のコマンド

1. コンテナを停止する

$ docker stop ubuntuLatest

2. コンテナを再起動する

$ docker start ubuntuLatest

3. Dockerのコンテナリストを確認する

起動中のコンテナ表示。

$ docker ps

停止中のコンテナ表示。

$ docker ps -a

4. コンテナを削除する

コンテナは停止していること。

$ docker rm [CONTAINER ID]

[CONTAINER ID]は、docker ps -aで確認したもの。

5. イメージを削除する

$ docker rmi [IMAGE ID]

[IMAGE ID]は、docker imagesで確認したもの。

注意

コマンドにすべてsudoをつけてませんが、Dockerのコンテナに普通に繋ぐと、rootユーザーになるからです。
通常の(Dockerでない)Ubuntuでやる場合は、sudoが必要かもしれません。

なお、root以外ユーザーを追加してそのユーザーでコンテナに入る方法は、いくつかググって試したのですが成功しませんでした。
仕方なくrootユーザーのままで作業しましたが、用途によってはだめでしょうね^^;

参考

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

Dockerコマンド

Dockerコマンド

よく使いそうなDockerコマンドをメモしておきます。

基本的なDockerコマンド

コマンド 内容
docker run <イメージ名> イメージ<イメージ名>を実行する。イメージがなければダウンロードしてくる
docker run --name <コンテナ名> <イメージ名> コンテナに名前<コンテナ名>を付けて実行する
docker run -it <イメージ名> bash イメージ<イメージ名>を実行する。コンテナでbashを起動する
docker run -d <イメージ名> イメージ<イメージ名>をバックグラウンドで実行する
docker run -v <パス名1>:<パス名2> <イメージ名> コンテナホストのパス<パス名1>とコンテナのパス<パス名2>をマウントする
docker run -e <環境変数名>=<値> <イメージ名> 環境変数<環境変数名>に値<値>を設定して実行する
docker pull <イメージ名> イメージ<イメージ名>をダウンロードする
docker start <コンテナ名> コンテナ<コンテナ名>を起動する
docker start -i <コンテナ名> コンテナ<コンテナ名>のSTDINに接続して起動する
docker stop <コンテナ名> コンテナ<コンテナ名>を停止する
docker attach --sig-proxy=false <コンテナ名> バックグラウンドで実行しているコンテナ<コンテナ名>に接続する。--sig-proxy=falseを付けるとターミナルでCtrl+Cが有効になる
docker exec -it <コンテナ名> bash コンテナ<コンテナ名>を別ターミナルで起動する
docker commit <コンテナ名> <タグ名> コンテナ<コンテナ名>にタグ<タグ名>を付けて保存する
docker rm <コンテナ名> コンテナ<コンテナ名>を削除する
docker rmi <イメージ名> イメージ<イメージ名>を削除する
docker logs <コンテナ名> コンテナ<コンテナ名>のログを表示する
docker ps 実行中のコンテナ一覧を表示する
docker ps -a 停止中を含めたコンテナ一覧を表示する

ネットワーク関連のDockerコマンド

コマンド 内容
docker network ls ネットワーク一覧を表示する
docker network create <ネットワーク名> ネットワーク<ネットワーク名>を作成する
docker run --network <ネットワーク名> <イメージ名> イメージ<イメージ名>をネットワーク<ネットワーク名>で実行する
docker run -d -p 8080:80 <イメージ名> イメージ<イメージ名>をバックグラウンドで実行する。コンテナ外部から8080ポートに接続すると、コンテナの80ポートにつながる
docker network rm <ネットワーク名> ネットワーク<ネットワーク名>を削除する
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <コンテナ名> 実行中のコンテナ<コンテナ名>のIPアドレスを取得する

Dockerfile関連のDockerコマンド

コマンド 内容
docker build --tag <タグ名> . カレントディレクトリにタグ<タグ名>を付けてイメージを作成する
docker build --tag <タグ名> -f <ファイル名> . Dockerファイル<ファイル名>でイメージを作成する

Docker Hub関連のDockerコマンド

Docker Hub

コマンド 内容
docker login Docker Hubのアカウントでログインする
docker tag <イメージ名> <タグ名> イメージ<イメージ名>にタグ<タグ名>を付ける
docker push <タグ名> タグ<タグ名>のイメージをアップロードする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails on docker がAWS S3 で AccessDeniedが出ることのデバッグ

今までVagrantで動かしていた、Railsをdockerに移したところ、何故かs3にホストしてある画像が取得出来なくなったのでその確認をしました。

1. dockerにaws-cliをインストールしてみる

  • ruby:2.6.5-slim-stretch イメージをベースにしていたことがありそもそもpythonが入っていなかったので色々とインストールしてみた
> docker-compose exec web bash
# curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
# python get-pip.py 
bash: python: command not found → インストールされていなかったので、apt install l-y pythonでまずpythonを導入
# apt install -y python
# python get-pip.py
# pip install awscli

2. s3の一覧を取得する

# aws s3 ls s3://[[バケットのURL]]

An error occurred (RequestTimeTooSkewed) when calling the ListObjectsV2 operation: The difference between the request ti
me and the current time is too large.

3. RequestTimeTooSkewed って?

https://qiita.com/sadakan5/items/4c0a394fd1d6be34efb2
を参照。

サーバーとAWSの時間がずれているとエラーになるとのことで date で時間を確認してみた

# date
Wed Mar 25 23:39:24 UTC 2020

ちなみに、EC2にホストしているサーバーで実行すると。。

# date
Thu Mar 26 23:11:39 UTC 2020

確かにずれています。。

ホストがずれているの?と見てみてもそんなことはないです。。
(ホストは日本時刻)

> date
2020年3月27日 8:12:11

システムを休止状態(Hybernate)にするとずれることがあると
https://docs.docker.com/docker-for-mac/troubleshoot/#known-issues

で、こうすればいいみたい

まずは、HostとGuestのタイムゾーンを合わせます。(タイムゾーンを無視して時間だけを同期してしまうので)

powershellだと
ホストの方をUTCにして再度時間を合わせてみる

> Get-Timezone
Id : Tokyo Standard Time 
...
> Set-Timezone -Id "UTC"

その後、同期するコマンドを実行します

(ホスト側で)
> docker run --rm --privileged alpine hwclock -s
> docker-compose exec web bash
# date
Fri Mar 27 08:28:29 UTC 2020

でなおった!

これ、順番逆にすると時計がずれたままで、直らないので要注意

ホスト側のタイムゾーンをTokyoに戻します

> Get-Timezone
Id : 
...
> Set-Timezone -Id "Tokyo Standard Time"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS S3 で AccessDeniedが出ることのデバッグ

今までVagrantで動かしていた、Railsをdockerに移したところ、何故かs3にホストしてある画像が取得出来なくなったのでその確認をしました。

1. dockerにaws-cliをインストールしてみる

  • ruby:2.6.5-slim-stretch イメージをベースにしていたことがありそもそもpythonが入っていなかったので色々とインストールしてみた
> docker-compose exec web bash
# curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
# python get-pip.py 
bash: python: command not found → インストールされていなかったので、apt install l-y pythonでまずpythonを導入
# apt install -y python
# python get-pip.py
# pip install awscli

2. s3の一覧を取得する

# aws s3 ls s3://[[バケットのURL]]

An error occurred (RequestTimeTooSkewed) when calling the ListObjectsV2 operation: The difference between the request ti
me and the current time is too large.

3. RequestTimeTooSkewed って?

https://qiita.com/sadakan5/items/4c0a394fd1d6be34efb2
を参照。

サーバーとAWSの時間がずれているとエラーになるとのことで date で時間を確認してみた

# date
Wed Mar 25 23:39:24 UTC 2020

ちなみに、EC2にホストしているサーバーで実行すると。。

# date
Thu Mar 26 23:11:39 UTC 2020

確かにずれています。。

ホストがずれているの?と見てみてもそんなことはないです。。
(ホストは日本時刻)

> date
2020年3月27日 8:12:11

システムを休止状態(Hybernate)にするとずれることがあると
https://docs.docker.com/docker-for-mac/troubleshoot/#known-issues

で、こうすればいいみたい

(ホスト側で)
> docker run --rm --privileged alpine hwclock -s
> docker-compose exec web bash
# date
Fri Mar 27 08:28:29 UTC 2020

でなおった... って、ホストの時刻をそのまま時差を考えずに同期していた!

一旦、ホストの方をUTCにして再度時間を合わせてみる

> Get-Timezone
Id : Tokyo Standard Time 
...
> Set-Timezone -Id "UTC"
(ホスト側で)
> docker run --rm --privileged alpine hwclock -s
> docker-compose exec web bash
# date
Fri Mar 27 08:28:29 UTC 2020

直らなかったです。再度docker for windowsを再起動しました

> Start-Process PowerShell.exe -Verb runas
> restart-service *docker*
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macにvirtualbox+alpine+docker+redmineの作業メモ

virtualboxのinstall

oracleのページからダウンロードしてinstall
ついで、extention packをダウンロード
(これはinstall後に設定から読み込む)

alpineのVM

ここからVIRTUALのやつのisoを落とす
VMを新規作成して、isoをdiskに設定して起動
# setup-alpine
でdiskにインストール
⭐️キーボード選択しない

docker

ここを参考にした
alpineにログイン
→キー入力がいまいちなのでVM直接早めてterminalからssh

うまくいかないので、Windowsでやる

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

Dockerと仮想マシンの違い

Dockerとは

Dockerとは軽量な仮想化環境を実現するためのツールです。
Dockerを利用すればOSの内部に独立したアプリケーションの実行環境を構築することができます。この構築環境をコンテナと呼びます。

コンテナ

コンテナ内のファイルシステムやリソースはベースOSと分離されており、コンテナ内は実行環境として独立しています。
コンテナを利用することで、1つのOS内に複数の実行環境を構築できます。

イメージ

イメージとはコンテナを生成する元になるものです。同じイメージを使えば、同じ Linux ディストリビューションで同じアプリケーションがインストールされた全く同じ環境を複製することができます。
また、Dockerではイメージを編集し、イメージの機能・内容を継承することもできます。
Dockerイメージを使うことで、従来必要だったプログラミング言語のインストールやフレームワークのインストールといった手間がかからず、パソコンのプログラミング環境を汚すことなく様々なアプリ開発に即・挑戦できるという訳です。

仮想マシン

仮想マシンとは仮想的にハードウェアを動作させることです。
仮想マシンには大きく分けて「ホスト型」と「ハイパーバイザー型」の2種類あります。

ホスト型とハイパーバイザー型

ホスト型とは、OSに仮想化ソフトウェアをインストールし、その上で仮想マシンを動かすことです。既存のサーバーを使えるため、手軽に利用できる一方で、ハードウェアにアクセスする際OSを経由しなければいけません。
ハイパーバイザー型とは、ホストOSを使わず直接サーバーにインストールし仮想マシンを動かすことです。ハードウェアのリソースを直接管理できます。

ホストOSとゲストOS

仮想化・仮想マシンに関連してよく出る用語が「ホストOS」と「ゲストOS」です。
ホストOSは仮想環境の土台となるOSのことで、ゲストOSは仮想マシン上にインストールされたOSのことです。
たとえば、Linuxサーバ上に仮想マシンを作り出しWindowsをインストールしたら、ホストOSはLinuxでゲストOSはWindowsということになります。

仮想マシンとDockerコンテナの違い

仮想マシンはマシン単位での仮想化であるのに対して、Dockerコンテナはプロセス単位での仮想化となっています。
仮想マシンは自由度が高い一方で、リソースの消費が激しいです。
それに対して、Dockerコンテナは仮想マシンよりも軽量ですが、OSをホストと共有するため自由度は下がります。

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

Darkを使用して、Slack App作成する

はじめに

本書では、Darkを使用したSlack Appの作成を行う。Darkに関しては、「新たな開発プラットフォーム "Dark/Darklang" を実際に触ってみて」を参考して頂ければと思う。

Darkでは、トレース駆動開発を駆使する事で、ビジネスロジックのみを記述するだけで開発が可能であるので、その点も注目して貰えたらと思う。

1. Slackアプリケーションの開発

Slack Appの開発を始めていく。アプリケーション名はsampleAppとした。

今回は、簡単にスラッシュコマンド/testを入力するとワニの画像が返されるようにする。

1.1. キャンバスの作成

開発する為にキャンバスを新規作成する。

アカウントには、darklang.com/a/USERNAME-CANVASNAMEからアクセスできる。今回は、Slack Appを作成するので、darklang.com/a/USERNAME-slackappと名付けた。

入力後にアクセスすると、キャンバスが立ち上がる。

1.2. Slackコマンドの追加

次に、Slack APIからSlack Appを新規作成する。

アプリケーションをワークスペースにインストールする為には権限が必要である。その為、筆者は独自のワークスペースを作成し、その中にSlack Appをセットアップする事にした。

Slackコマンドに/testコマンドを追加し、USERNAME-CANVASNAME.builtwithdark.com/testでリクエストURLを指定する。今回は以下の様に設定した。

Screen Shot 2020-03-27 at 1.54.13.png

必要に応じて、ここでSlackbot等の他の機能を追加できるが、今回はこれをベースに開発していく。

1.3. OAuthのセットアップ

1.3.1 リダイレクトURLの設定

アプリを配布できるようにする為、OAuthをセットアップする。Slack APIのOAuth & Permissionsから、リダイレクトURLを追加する。

Screen Shot 2020-03-24 at 10.55.51.png

DarkではOAuthの使用する際は以下の形式でURLを指定する必要があるので、それに則って記述する。

https://USERNAME-CANVASNAME.builtwithdark.com/OAUTH-REDIRECT

URLを保存後、Settings/Manage Distributionから共有可能なURLをブラウザのアドレスバーにコピーする。アクセスするとアプリケーションをインストールできるのでインストールする。この段階ではアクセスしてもバックエンドのロジックは何も記述していない為、以下の様なエラーが表示される。

404 Not Found: No route matches

しかし、この様な振る舞いを行う事でDarkは痕跡を確認する事ができ、それをトレースする事で開発を行う。

筆者自身、このトレース駆動開発にはまだ慣れていない部分もあるが、敢えてこの様に異常検知を起こす事でアクセスに必要な情報をトレースして開発を行う事がDarkを使用する上での1つのメリットである。

Darkのキャンバス(https://darklang.com/a/USERNAME-slackapp)に戻り、セクションを確認してみると404セクションに/oauth-redirectが表示されている事が確認できる。

Screen Shot 2020-03-23 at 4.41.38.png

この404にある/oauth-redirectをプロダクショントレースしてバックエンドを構築していく。+をクリックすると、GETメソッドのOAuthリクエストに応答するHTTPハンドラを作成する。

Screen Shot 2020-03-23 at 5.11.57.png

作成したものを確認してみると、SlackがDarkアプリに対して行ったリクエストを示すトレースが表示されている。ここには、Slackに返答する際に必要なコードが含まれる。(一部個人情報を含む為、加工している)

1.3.2. トークンの取得

Slackアプリに送信する為にはclient_idclient_secretが必要である。これらの情報は、SlackのSettings/App Credentialsから確認する事ができる。

Screen Shot 2020-03-27 at 1.58.55.png

確認後、作成した/oauth-redirectハンドラにコードを記述していく。ここで、client_idclient_secretをペーストする際は最初に文字リテラル"を入力してからでないと、Darkではフロート型の様に扱われ、全ての文字列がペーストされない。

Screen Shot 2020-03-27 at 0.16.49.png

また、実行すると偶にoauth_authorization_url_mismatchと返される場合があるが、それはOAuthの認証URLが異なるからである。どちらのURLを使用するかは、Settings/App CredentialsのClient IDを見ると右下に小さく書いているので、それで判断する事が可能である。

# どちらかのURLを使用する
https://slack.com/api/oauth.access
https://slack.com/api/oauth.v2.access

※ 今回、筆者はoauth.v2.accessを使用しているが、oauth.v2.accessからレスポンスで返されるJSONの仕様が変更されている。その為、oauth.accessを使用する場合は、後述で説明するトークン保存時のパラメータの指定方法が異なるので注意して欲しい。

これにより、Slack APIの一部(oauth.v2.access)が呼び出され、リクエストされたSlackにアクセス可能になる。実行すると、正しくレスポンスが返されればteam.idaccess_tokenが取得できる。

しかし、コードの有効期限が切れると以下の様なエラーが表示される。その場合は、面倒だが再度ブラウザから共有リンクを開き、認証を行う必要がある。

Screen Shot 2020-03-23 at 21.28.21.png

1.3.2. トークンの保存

次に、取得したトークンとデータストアに保存する。アドレスバーから新しいデートストアを作成し、保存するフィールドにスキーマを設定する。bot_tokenoauth.v2.accessを使用する場合は不要である。

Screen Shot 2020-03-23 at 21.59.02.png

データストアの作成が完了すれば、/oauth-redirectにロジックを記述していく。

Screen Shot 2020-03-27 at 0.15.31.png

1.4. アプリケーション機能の構築

ワークスペースにアプリケーションをインストールしたので、Slackを起動して確認してみる。設定したスラッシュコマンド/testを入力してもまだロジックが実装されていない為、エラーが表示される。

Screen Shot 2020-03-23 at 22.50.43.png

しかし、このトリガーからDarkの404セクションにルートが表示されるので、それをトレースして機能を構築していく。404セクションからエンドポイントを作成するとトレースを操作可能である。

Screen Shot 2020-03-23 at 22.43.57.png

今回のアプリケーションでは以下の様に実装した。リクエストURLを取得し、そのリクエストに対してテキストを返す。

Screen Shot 2020-03-27 at 0.31.16.png

1.5. 動作検証

実際にSlack側で動作させてみる。/testと入力すると、Darkで設定したテキストと成功した事を証明するJSONが出力された事が確認できる。

ezgif.com-video-to-gif (3).gif

JSONの出力を非表示にしたい場合は、Http::respondWithTextを使用して200コードに対して空白を指定すると表示されなくなる。

Screen Shot 2020-03-27 at 0.44.35.png

以上で、DarkでSlack Appの実装する事ができた。

2. データストアを活用したアプリケーションの実装

応用として、データストアに保存された50音を行ごとにランダムに出力する様に実装してみる。

まず、RandomMessagesと言うデータストアを用意し、フィールドにmessageと言うスキーマを用意する。そこにREPLでデータストアに対して登録を行うaddMessagesを用意する。続けて、データストアに登録された情報を確認する為にREPLでsetMessagesも用意した。

Screen Shot 2020-03-27 at 1.09.40.png

次に、先程使用した/testのロジックを一部修正し、その結果をSlack側に送信する。

Screen Shot 2020-03-27 at 1.11.13.png

追加した変数の概要は以下の通りである。

変数名 内容
allMessages RandomMessagesに保存されている情報を全て取得し、配列に保存する。
messageCount 配列の長さを取得する。
messageCountLessOne 配列は0から始まる為、1除算する。
index ランダム値を取得する。範囲として0からmessageCountLessOneを指定する。
message indexの値に該当する情報をデータストアから取得する。

実際に動かしてみると、以下の様にランダムに結果が表示される事がわかる。先程、実装したHttp::respondWithTextによりJSONが出力されない事も併せて見て貰うと良い。

ezgif.com-video-to-gif (4).gif

3. 最後に

今回は、DarkでSlack Appの実装を行った。筆者は、Slack Appの開発は初めてであった為、Dark以外でいくつか躓く点が多かったのだが、開発した事のある方であれば比較的容易に開発できるのではないだろうか。実際に今回開発した全体図を見ると、非常に少ないコードで開発できている事がわかる。

Screen Shot 2020-03-27 at 1.41.55.png

また、Darkでは定義した変数名をクリックすると即座に値を確認できるので、意図した値が返ってきているかどうかを知ることができる。これにより、コードを記述している間も修正箇所に気づきやすいので、逐一デバッグを行い確認する必要はない。

最後に開発を通して発見した事だが、Darkで日本語文字列を入力しようとすると変換をする際にスペースも誤入力されてしまう様である。この点に関しては、今後の改善希望として報告しておこうと思う。

【2020/03/27 03:43追記】
ベータ版と言う事もあり、現段階ではテキスト構成のサポートがまだ十分ではないとの事。回避策として、もし日本語入力を行いたい際はコピー&ペーストを使用して入力して欲しい。

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

mozilla製オープンソース翻訳プラットフォームpontoonのインストール方法

翻訳自体は古くからあるけれど、翻訳に関するツール、特にオープンソースのツールはそんなに多くありません。
この記事はその中の一つpontoonのインストールする記事です。1
読み方は多分ポンツーンです。

用意するものの用意

これとかこれを参考にdockerとgitをインストールする。そっちの方が詳しいのであまり説明しません。
docker-composeも必要だけどdockerインストールしたらついてくるはず。

windowsの場合

chocolateyを使用して以下のコマンドを打てば簡単に準備できる。使わなくてもok。パッケージ管理してくれるのは楽だよってだけ。
choco install make git cygwin

ソースを持ってくる

公式にはフォークして使ってと書いてあるけど理由は不明。普通に持ってきていいはず。好きなディレクトリで以下のコマンドを打てばいいだけ。
分かりにくいのでosのターミナルは$で、dockerのターミナルは%にしています。
$ git clone https://github.com/mozilla/pontoon.git

windowsの場合このコマンドを打つ前に以下のコマンドで改行コードを書き換えないようにする必要があります。
$ git config --system --unset core.autocrlf
$ git config --global core.autocrlf false

dockerのターミナルを開く

dockerのターミナルを開いたときにでるipアドレスを確認しておく。
1.jpg
今回は192.168.99.101です

pontoonのビルド

dockerのターミナルからpontoonのルートディレクトリで以下のコマンドを打つ。
% make build SITE_URL="{確認したipアドレス}"

今回はmake build SITE_URL="http://192.168.99.101:8000"です
初回はやたら長い

pontoonを走らせる

以下のコマンドでpontoonを起動する。
% make run

さっきみたipアドレスをブラウザに打ち込み、エラーが出てなければインストール成功です。
2.jpg

プロジェクトの作成

pontoonのドキュメントはあまり優しくないというか使い方に関しては説明が少ない。のでここにやったことを書いておきます。

  1. 管理ユーザーの作成 以下のコマンドで管理ユーザーを作成します。

% make setup

作成する時はこの三つが聞かれますがなぜかユーザー名とメールアドレスを空にしても何も言われません。

  • pontoon以外で任意のユーザー名
  • メールアドレス(なくても可)
  • パスワード

公式にはサーバーを立ち上げて置いてと書いてあったけどあれはpostgresのサーバーのことを言っているはず。

  1. ログイン
    管理ユーザーを作ったら画面右上のsign inからログインします。

  2. 管理コンソールを開く
    右上のボタンから「Admin」、「ADD NEW PROJECT」を押すか、または以下のurlからアクセス。
    http://192.168.99.101:8000/admin/projects/

4.nameの所に適当な名前を入れてlocaleのとこのavailableからjapaneseを探してクリック。探すのがめんどくさければmove allをクリックしてlocalizableに入れておく

5.jpg

5.data sourceをrepositoryからdatabaseに変えてstringsに改行区切りでテキストを与える
6.jpg

6.オプションを自由につけたら一番下のsave projectをクリック

7.上手くいったらプロジェクトが登録されるはず
7.jpg

8.後は素敵な翻訳ライフを!

8.jpg

翻訳業界はやや閉鎖的というか使っているツールが古いというかtradusがずっと天下を取っている。
翻訳ツールのオープンソース化が進んでほしいです


  1. 公式的にはローカライゼーションツールとしているけど、翻訳していることには変わらないのでそう呼ぶ 

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

[後編]人狼知能をDockerで動かしたかった

0. はじめに

Dockerの知識がほぼ0の私が,思いつきで進めた内容の記録です.
この記事は前後編に分かれています.この記事は後編です.
前編はコチラ

5. Dockerを使ってみる

Docker上でサーバが動くようにすれば,環境構築に悩まなくて済むし,複数台の構築も楽になるのではないか?と考えました.

5.1. 要件

  • 親しみのあるディストリビューションをベースにしたい
  • 実行したらサーバが走るようにしたい
  • どの言語のエージェントも動かしたい
  • 設定ファイルや参加させるエージェントなどは,実行する度に変えたい

5.2. 実装

実際のDockerfile(長いです)
# BaseImage is Ubuntu18.04
FROM ubuntu:18.04

# Install some software package and make temporary directory
RUN apt update && \
    apt install -y --no-install-recommends wget unzip bzip2 vim && \
    mkdir /tmp/AiwolfTmp

# Install Java8 (OpenJDK)
RUN apt install -y openjdk-8-jdk

# Download aiwolf-server(ver0.5.6)
RUN wget http://aiwolf.org/control-panel/wp-content/uploads/2014/03/aiwolf-ver0.5.6.zip -O /tmp/AiwolfTmp/aiwolf-platform.zip && \
    mkdir /home/aiwolf-platform && \
    unzip -j /tmp/AiwolfTmp/aiwolf-platform.zip -d /home/aiwolf-platform

# Install .NET Core SDK 2.2
RUN wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O /tmp/AiwolfTmp/packages-microsoft-prod.deb && \
    dpkg -i /tmp/AiwolfTmp/packages-microsoft-prod.deb && \
    apt install -y apt-transport-https && \
    apt update && \
    apt install -y dotnet-sdk-2.2

# Download C# Agent ClientStarter(ver2.0.1)
RUN wget https://github.com/AIWolfSharp/AIWolf_NET/releases/download/v2.0.1/ClientStarter-2.0.1-linux-x64.tgz -O /tmp/AiwolfTmp/aiwolf-client-starter.tgz && \
    mkdir /home/aiwolf-client-starter && \
    tar xzvf /tmp/AiwolfTmp/aiwolf-client-starter.tgz -C /home/aiwolf-client-starter --strip=1 

# Install Miniconda3(ver4.7.12.1)
ENV PATH=/root/miniconda3/bin:$PATH
RUN wget --no-check-certificate https://repo.anaconda.com/miniconda/Miniconda3-4.7.12.1-Linux-x86_64.sh -O /tmp/AiwolfTmp/miniconda.sh && \
    bash /tmp/AiwolfTmp/miniconda.sh -b

# Setup miniconda
RUN conda update conda -y && \
    conda init bash

# Create yaml file to reproduction official environment
RUN { \
        echo 'name: aiwolf'; \
        echo 'channels:'; \
        echo '  - conda-forge'; \
        echo '  - defaults'; \
        echo 'dependencies:'; \
        echo '  - _libgcc_mutex=0.1=main'; \
        echo '  - _tflow_select=2.3.0=mkl'; \
        echo '  - absl-py=0.7.1=py36_0'; \
        echo '  - alabaster=0.7.10=py36h306e16b_0'; \
        echo '  - anaconda-client=1.6.14=py36_0'; \
        echo '  - anaconda-navigator=1.8.7=py36_0'; \
        echo '  - anaconda-project=0.8.2=py36_0'; \
        echo '  - asn1crypto=0.24.0=py_1'; \
        echo '  - astor=0.8.0=py36_0'; \
        echo '  - astroid=1.6.3=py36_0'; \
        echo '  - astropy=3.0.2=py36h3010b51_1'; \
        echo '  - attrs=18.1.0=py_1'; \
        echo '  - babel=2.5.3=py36_0'; \
        echo '  - backcall=0.1.0=py36_0'; \
        echo '  - backports=1.0=py_2'; \
        echo '  - backports.shutil_get_terminal_size=1.0.0=py36_2'; \
        echo '  - beautifulsoup4=4.6.0=py36_1'; \
        echo '  - bitarray=0.8.1=py36h14c3975_1'; \
        echo '  - bkcharts=0.2=py36_0'; \
        echo '  - blas=1.0=mkl'; \
        echo '  - blaze=0.11.3=py36_0'; \
        echo '  - bleach=2.1.3=py36_0'; \
        echo '  - blosc=1.16.3=hd408876_0'; \
        echo '  - bokeh=0.12.16=py36_0'; \
        echo '  - boto=2.48.0=py36_1'; \
        echo '  - bottleneck=1.2.1=py36h035aef0_1'; \
        echo '  - bzip2=1.0.8=h7b6447c_0'; \
        echo '  - c-ares=1.15.0=h7b6447c_1001'; \
        echo '  - ca-certificates=2020.1.1=0'; \
        echo '  - certifi=2018.4.16=py36_0'; \
        echo '  - cffi=1.11.5=py36h9745a5d_1001'; \
        echo '  - chainer=6.3.0=py_0'; \
        echo '  - chardet=3.0.4=py36_1003'; \
        echo '  - click=6.7=py_1'; \
        echo '  - cloudpickle=0.5.3=py36_0'; \
        echo '  - clyent=1.2.2=py36_1'; \
        echo '  - colorama=0.3.9=py36_0'; \
        echo '  - conda=4.5.4=py36_0'; \
        echo '  - conda-build=3.10.5=py36_0'; \
        echo '  - conda-env=2.6.0=1'; \
        echo '  - conda-verify=2.0.0=py36h98955d8_0'; \
        echo '  - contextlib2=0.5.5=py36_0'; \
        echo '  - cryptography=2.2.2=py36h14c3975_0'; \
        echo '  - curl=7.61.0=h84994c4_0'; \
        echo '  - cycler=0.10.0=py36_0'; \
        echo '  - cython=0.28.2=py36h14c3975_0'; \
        echo '  - cytoolz=0.9.0.1=py36h14c3975_1'; \
        echo '  - dask=0.17.5=py36_0'; \
        echo '  - dask-core=0.17.5=py36_0'; \
        echo '  - datashape=0.5.4=py36_1'; \
        echo '  - dbus=1.13.12=h746ee38_0'; \
        echo '  - decorator=4.3.0=py36_0'; \
        echo '  - distributed=1.21.8=py36_0'; \
        echo '  - docutils=0.14=py36_1001'; \
        echo '  - entrypoints=0.2.3=py36_2'; \
        echo '  - et_xmlfile=1.0.1=py36_0'; \
        echo '  - expat=2.2.6=he6710b0_0'; \
        echo '  - fastcache=1.0.2=py36h14c3975_2'; \
        echo '  - filelock=3.0.4=py36_0'; \
        echo '  - flask=1.0.2=py36_0'; \
        echo '  - flask-cors=3.0.4=py36_0'; \
        echo '  - fontconfig=2.13.0=h9420a91_0'; \
        echo '  - freetype=2.9.1=h8a8886c_1'; \
        echo '  - gast=0.2.2=py36_0'; \
        echo '  - gevent=1.3.0=py36h14c3975_0'; \
        echo '  - glib=2.63.1=h5a9c865_0'; \
        echo '  - glob2=0.6=py36_1'; \
        echo '  - gmp=6.1.2=h6c8ec71_1'; \
        echo '  - gmpy2=2.0.8=py36h10f8cd9_2'; \
        echo '  - greenlet=0.4.13=py36h14c3975_0'; \
        echo '  - gst-plugins-base=1.14.0=hbbd80ab_1'; \
        echo '  - gstreamer=1.14.0=hb453b48_1'; \
        echo '  - h5py=2.7.1=py36ha1f6525_2'; \
        echo '  - hdf5=1.10.2=hba1933b_1'; \
        echo '  - heapdict=1.0.0=py36_2'; \
        echo '  - html5lib=1.0.1=py36_0'; \
        echo '  - icu=58.2=h9c2bf20_1'; \
        echo '  - idna=2.6=py36h82fb2a8_1'; \
        echo '  - imageio=2.3.0=py36_0'; \
        echo '  - imagesize=1.0.0=py36_0'; \
        echo '  - intel-openmp=2019.4=243'; \
        echo '  - ipykernel=4.8.2=py36_0'; \
        echo '  - ipython=6.4.0=py36_1'; \
        echo '  - ipython_genutils=0.2.0=py36_0'; \
        echo '  - ipywidgets=7.2.1=py36_0'; \
        echo '  - isort=4.3.4=py36_0'; \
        echo '  - itsdangerous=0.24=py36_1'; \
        echo '  - jdcal=1.4=py36_0'; \
        echo '  - jedi=0.12.0=py36_1'; \
        echo '  - jinja2=2.10=py36_0'; \
        echo '  - jpeg=9b=h024ee3a_2'; \
        echo '  - jsonschema=2.6.0=py36_0'; \
        echo '  - jupyter=1.0.0=py36_7'; \
        echo '  - jupyter_client=5.2.3=py36_0'; \
        echo '  - jupyter_console=5.2.0=py36_1'; \
        echo '  - jupyter_core=4.4.0=py36_0'; \
        echo '  - jupyterlab=0.32.1=py36_0'; \
        echo '  - jupyterlab_launcher=0.10.5=py36_0'; \
        echo '  - keras=2.2.4=0'; \
        echo '  - keras-applications=1.0.7=py_0'; \
        echo '  - keras-base=2.2.4=py36_0'; \
        echo '  - keras-preprocessing=1.0.9=py_1'; \
        echo '  - kiwisolver=1.0.1=py36hf484d3e_0'; \
        echo '  - lazy-object-proxy=1.3.1=py36h14c3975_2'; \
        echo '  - libcurl=7.61.0=h1ad7b7a_0'; \
        echo '  - libedit=3.1.20181209=hc058e9b_0'; \
        echo '  - libffi=3.2.1=hd88cf55_4'; \
        echo '  - libgcc-ng=9.1.0=hdf63c60_0'; \
        echo '  - libgfortran-ng=7.3.0=hdf63c60_0'; \
        echo '  - libpng=1.6.37=hbc83047_0'; \
        echo '  - libprotobuf=3.7.1=hd408876_0'; \
        echo '  - libsodium=1.0.16=h1bed415_0'; \
        echo '  - libssh2=1.8.0=h9cfc8f7_4'; \
        echo '  - libstdcxx-ng=9.1.0=hdf63c60_0'; \
        echo '  - libtiff=4.1.0=h2733197_0'; \
        echo '  - libuuid=1.0.3=h1bed415_2'; \
        echo '  - libxcb=1.13=h1bed415_1'; \
        echo '  - libxml2=2.9.9=hea5a465_1'; \
        echo '  - libxslt=1.1.33=h7d1a2b0_0'; \
        echo '  - llvmlite=0.23.1=py36hdbcaa40_0'; \
        echo '  - locket=0.2.0=py36_1'; \
        echo '  - lxml=4.2.1=py36h23eabaa_0'; \
        echo '  - lz4-c=1.8.1.2=h14c3975_0'; \
        echo '  - lzo=2.10=h49e0be7_2'; \
        echo '  - markdown=3.1.1=py36_0'; \
        echo '  - markupsafe=1.0=py36h14c3975_1'; \
        echo '  - matplotlib=2.2.2=py36hb69df0a_2'; \
        echo '  - mccabe=0.6.1=py36_1'; \
        echo '  - mistune=0.8.3=py_0'; \
        echo '  - mkl=2018.0.3=1'; \
        echo '  - mkl_fft=1.0.1=py36h3010b51_0'; \
        echo '  - mkl_random=1.0.1=py36h629b387_0'; \
        echo '  - mock=3.0.5=py36_0'; \
        echo '  - more-itertools=4.1.0=py36_0'; \
        echo '  - mpc=1.1.0=h10f8cd9_1'; \
        echo '  - mpfr=4.0.1=hdf1c602_3'; \
        echo '  - mpmath=1.0.0=py36_2'; \
        echo '  - msgpack-python=0.6.1=py36hfd86e86_1'; \
        echo '  - multipledispatch=0.5.0=py36_0'; \
        echo '  - navigator-updater=0.2.1=py36_0'; \
        echo '  - nbconvert=5.3.1=py36_0'; \
        echo '  - nbformat=4.4.0=py36_0'; \
        echo '  - ncurses=6.2=he6710b0_0'; \
        echo '  - networkx=2.1=py36_0'; \
        echo '  - nltk=3.3.0=py36_0'; \
        echo '  - nose=1.3.7=py36_2'; \
        echo '  - notebook=5.5.0=py36_0'; \
        echo '  - numba=0.38.0=py36h637b7d7_0'; \
        echo '  - numexpr=2.6.5=py36_0'; \
        echo '  - numpy=1.14.3=py36hcd700cb_1'; \
        echo '  - numpy-base=1.14.3=py36h9be14a7_1'; \
        echo '  - numpydoc=0.8.0=py36_0'; \
        echo '  - odo=0.5.1=py36_0'; \
        echo '  - olefile=0.45.1=py36_0'; \
        echo '  - openpyxl=2.5.3=py36_0'; \
        echo '  - openssl=1.0.2u=h7b6447c_0'; \
        echo '  - packaging=17.1=py36_0'; \
        echo '  - pandas=0.23.0=py36h637b7d7_0'; \
        echo '  - pandoc=2.2.3.2=0'; \
        echo '  - pandocfilters=1.4.2=py36_1'; \
        echo '  - parso=0.2.0=py36_0'; \
        echo '  - partd=0.3.8=py36_0'; \
        echo '  - patchelf=0.10=he6710b0_0'; \
        echo '  - path.py=11.0.1=py36_0'; \
        echo '  - pathlib2=2.3.2=py36_0'; \
        echo '  - patsy=0.5.0=py36_0'; \
        echo '  - pbr=5.2.0=py_0'; \
        echo '  - pcre=8.43=he6710b0_0'; \
        echo '  - pep8=1.7.1=py36_0'; \
        echo '  - pexpect=4.5.0=py36_0'; \
        echo '  - pickleshare=0.7.4=py36_0'; \
        echo '  - pillow=5.1.0=py36heded4f4_0'; \
        echo '  - pip=20.0.2=py36_1'; \
        echo '  - pkginfo=1.4.2=py36_0'; \
        echo '  - pluggy=0.6.0=py36_0'; \
        echo '  - ply=3.11=py36_0'; \
        echo '  - prompt_toolkit=1.0.15=py36_0'; \
        echo '  - protobuf=3.7.1=py36he6710b0_0'; \
        echo '  - psutil=5.4.5=py36h14c3975_0'; \
        echo '  - ptyprocess=0.5.2=py36h69acd42_0'; \
        echo '  - py=1.5.3=py36_0'; \
        echo '  - pycodestyle=2.4.0=py36_0'; \
        echo '  - pycosat=0.6.3=py36h7b6447c_0'; \
        echo '  - pycparser=2.18=py36_1'; \
        echo '  - pycrypto=2.6.1=py36h14c3975_9'; \
        echo '  - pycurl=7.43.0.1=py36hb7f436b_0'; \
        echo '  - pyflakes=1.6.0=py_1'; \
        echo '  - pygments=2.2.0=py36_0'; \
        echo '  - pylint=1.8.4=py36_0'; \
        echo '  - pyodbc=4.0.23=py36hf484d3e_0'; \
        echo '  - pyopenssl=18.0.0=py36_0'; \
        echo '  - pyparsing=2.2.0=py36_0'; \
        echo '  - pyqt=5.9.2=py36h05f1152_2'; \
        echo '  - pysocks=1.6.8=py36_0'; \
        echo '  - pytables=3.4.3=py36h02b9ad4_2'; \
        echo '  - pytest=3.5.1=py36_0'; \
        echo '  - pytest-arraydiff=0.2=py36h39e3cac_0'; \
        echo '  - pytest-astropy=0.3.0=py36_0'; \
        echo '  - pytest-doctestplus=0.1.3=py36_0'; \
        echo '  - pytest-openfiles=0.3.0=py36_0'; \
        echo '  - pytest-remotedata=0.2.1=py36_0'; \
        echo '  - python=3.6.5=hc3d631a_2'; \
        echo '  - python-dateutil=2.7.3=py36_0'; \
        echo '  - pytz=2018.4=py36_0'; \
        echo '  - pywavelets=0.5.2=py36h035aef0_2'; \
        echo '  - pyyaml=3.12=py36_1'; \
        echo '  - pyzmq=17.0.0=py36h14c3975_3'; \
        echo '  - qt=5.9.6=h8703b6f_2'; \
        echo '  - qtawesome=0.4.4=py36_0'; \
        echo '  - qtconsole=4.3.1=py36_0'; \
        echo '  - qtpy=1.4.1=py36_0'; \
        echo '  - readline=7.0=h7b6447c_5'; \
        echo '  - requests=2.18.4=py36he2e5f8d_1'; \
        echo '  - rope=0.10.7=py36_0'; \
        echo '  - ruamel_yaml=0.15.35=py36h14c3975_1'; \
        echo '  - scikit-image=0.13.1=py36h14c3975_1'; \
        echo '  - scikit-learn=0.19.1=py36hedc7406_0'; \
        echo '  - scipy=1.1.0=py36hd20e5f9_0'; \
        echo '  - seaborn=0.8.1=py36_0'; \
        echo '  - send2trash=1.5.0=py36_0'; \
        echo '  - setuptools=46.0.0=py36_0'; \
        echo '  - simplegeneric=0.8.1=py36_2'; \
        echo '  - singledispatch=3.4.0.3=py36_0'; \
        echo '  - sip=4.19.8=py36hf484d3e_0'; \
        echo '  - six=1.11.0=py36_1001'; \
        echo '  - snappy=1.1.7=hbae5bb6_3'; \
        echo '  - snowballstemmer=1.2.1=py36_0'; \
        echo '  - sortedcollections=0.6.1=py36_0'; \
        echo '  - sortedcontainers=1.5.10=py36_0'; \
        echo '  - sphinx=1.7.4=py36_0'; \
        echo '  - sphinxcontrib-websupport=1.0.1=py36_0'; \
        echo '  - spyder=3.2.8=py36_0'; \
        echo '  - sqlalchemy=1.2.7=py36h6b74fdf_0'; \
        echo '  - sqlite=3.31.1=h7b6447c_0'; \
        echo '  - statsmodels=0.9.0=py36h3010b51_1000'; \
        echo '  - sympy=1.1.1=py36_0'; \
        echo '  - tbb=2020.0=hfd86e86_0'; \
        echo '  - tbb4py=2020.0=py36hfd86e86_0'; \
        echo '  - tblib=1.3.2=py36_0'; \
        echo '  - tensorboard=1.13.1=py36_0'; \
        echo '  - tensorflow=1.13.1=mkl_py36h27d456a_0'; \
        echo '  - tensorflow-base=1.13.1=mkl_py36h7ce6ba3_0'; \
        echo '  - tensorflow-estimator=1.13.0=py_0'; \
        echo '  - termcolor=1.1.0=py36_1'; \
        echo '  - terminado=0.8.1=py36_1'; \
        echo '  - testpath=0.3.1=py36_0'; \
        echo '  - tk=8.6.8=hbc83047_0'; \
        echo '  - toolz=0.9.0=py36_0'; \
        echo '  - tornado=5.0.2=py36h14c3975_0'; \
        echo '  - traitlets=4.3.2=py36_0'; \
        echo '  - typing=3.6.4=py36_0'; \
        echo '  - typing_extensions=3.7.2=py36_1000'; \
        echo '  - unicodecsv=0.14.1=py36_0'; \
        echo '  - unixodbc=2.3.7=h14c3975_0'; \
        echo '  - urllib3=1.22=py36hbe7ace6_0'; \
        echo '  - wcwidth=0.1.7=py36_0'; \
        echo '  - webencodings=0.5.1=py36_1'; \
        echo '  - werkzeug=0.14.1=py36_0'; \
        echo '  - wheel=0.34.2=py36_0'; \
        echo '  - widgetsnbextension=3.2.1=py36_0'; \
        echo '  - wrapt=1.10.11=py36h14c3975_2'; \
        echo '  - xlrd=1.1.0=py36_1'; \
        echo '  - xlsxwriter=1.0.4=py36_0'; \
        echo '  - xlwt=1.3.0=py36_0'; \
        echo '  - xz=5.2.4=h14c3975_4'; \
        echo '  - yaml=0.1.7=had09818_2'; \
        echo '  - zeromq=4.2.5=hf484d3e_1'; \
        echo '  - zict=0.1.3=py36_0'; \
        echo '  - zlib=1.2.11=h7b6447c_3'; \
        echo '  - zstd=1.3.7=h0b5b093_0'; \
        echo '  - pip:'; \
        echo '    - grpcio==1.20.1'; \
        echo '    - simpleai==0.8.2'; \
        echo 'prefix: /root/miniconda3/envs/aiwolf'; \
    } > /tmp/AiwolfTmp/aiwolf.yaml

# Building a Virtual Environment
RUN conda env create -f /tmp/AiwolfTmp/aiwolf.yaml && \
    echo 'conda activate aiwolf' >> /root/.bashrc && \
    echo '処理の完了までに時間を要する場合があります.' && \
    echo 'Processing may take some time to complete.'

# Delete temporary directory
RUN rm -r /tmp/AiwolfTmp/

# Delete Werewolf Intelligence Configuration File
RUN rm /home/aiwolf-platform/AutoStarter.ini && \
    rm /home/aiwolf-platform/SampleSetting.cfg

# Remake AutoStarter.sh
RUN echo 'java -cp /home/aiwolf-platform/aiwolf-server.jar:/home/aiwolf-platform/aiwolf-common.jar:/home/aiwolf-platform/aiwolf-client.jar:/home/aiwolf-platform/aiwolf-viewer.jar:/home/aiwolf-platform/jsonic-1.3.10.jar org.aiwolf.ui.bin.AutoStarter /home/aiwolf-platform/AutoStarter.ini' > /home/aiwolf-platform/AutoStarter.sh

# 
CMD [ "conda", "run", "-n", "aiwolf", "/bin/bash", "/home/aiwolf-platform/AutoStarter.sh" ]


Dockerfileの折りたたみを開かなくても済むように,書いてある内容の流れを説明します.

  1. ubuntu:18.04のイメージをベースに作成
  2. wgetやunzipなど,必要なソフトウェアパッケージのインストール
  3. OpenJDK-8をインストール
  4. 人狼知能サーバをダウンロード・展開
  5. .NET Core SDK2.2をインストール
  6. C#エージェントに必要なクライアントスターターと呼ばれるファイルをダウンロード・展開
  7. Miniconda3のインストール・セットアップ
  8. Python3.6.5+必要なパッケージについて書かれたyamlファイルを作成
  9. yamlファイルを元にminiconda上に仮想環境の構築
  10. 4で展開した時にできたAutoStarter.iniとSampleSetting.cfgファイルを削除
  11. CMDでサーバが実行するように設定.この時conda runコマンドから実行するように

minicondaの仮想環境は,一度手元で作った環境をconda env exportを使って,yamlファイルに吐き出したものを使用しています.なぜ,Dockerfileをビルドする際にホスト側からyamlファイルをコピーしないのかですが,Pythonエージェント実行の環境が変わる可能性が低いこと・変わるとしたらサーバのバージョン含めてPython以外の部分も変わる可能性が高いことなどから,Dockerfile内でyamlファイルを作成するようにしてしまった方が,扱うファイルが少なくて楽だろうという個人的見解からです.

5.3. 実装中に悩んだところ(備忘録)

  • DockerfileからMiniconda(Anaconda)上に仮想環境を作るのが難しい
    過去に作られた環境を今再現しようと思うと,結構難しかったです.せっかく旧バージョンのパッケージをインストールしておいたのに,他のパッケージの依存ライブラリであったがために上書きされていたってこともありました.解決策として,ubuntuイメージを走らせて,その中で依存関係を気にしながらパッケージを一通りインストールし,出来上がったものをexportしてyamlにし,実環境に反映しました.yamlからcreateして作成する環境はそのまま再現される仕様を使っています.

  • 変更点の多いレイヤーは次のレイヤーに進むまでに時間がかかる
    これは単純に私の無知が由来ですが,pythonのパッケージのインストールが終わった後,次のコマンドがなかなか実行されず,ctrl+cで抜けては頭に「??」を浮かべていました.一度根気よく待ってみたところ,何の問題もなく次に進んだので,「あ,多くの変更をおこなったレイヤーは,その分次に進むのにも時間がかかるのか」 と理解しました.

  • Pythonがアクティベートした環境で実行されない
    JavaのサーバがPythonエージェントを実行する手段はProcessBuilderpythonを呼び出しています.このProcessBuilderから呼ばれるpythonでは作成した仮想環境をアクティベートしてあっても,baseが呼び出されてしまいます.おそらく環境変数のあたりの問題でしょう.サーバを書き換えてpython/root/miniconda3/envs/[myenv]/bin/pythonに置き換えれば正しく動きますが,公式GitHubからソースを取ってきて書き換えてコンパイルしてと手順を踏むのは面倒くさすぎるので他の方法を考えました.結果,conda run -n myenv cmdで実行することにしました.これは,指定した仮想環境内で,引数に与えたコマンドを実行するものであり,baseと同じポジションに特定の仮想環境を割り当てた状態でコマンドが実行できます.ただしこれにも,標準出力・標準エラー出力がconda runにバッファされるという問題があります.つまり実行中に表示されるはずのありとあらゆる出力が,プログラム実行後にしか表示されないのです.

5.4. 使い方(過去に人狼知能を触ったことがある人向け)

折りたたみ
  1. AutoStarter.iniとSampleSetting.cfgを用意する
  2. AutoStarter.iniのlib,log,C#,settingの項目を書き換える.C#は/usr/bin/dotnetに,そのほかは自由に書き換えてください.ただし,lib・logのフォルダとsettingのファイルはホスト側からマウントする前提なので,マウントした先を書いておくこと
  3. -vオプションを用いて,SampleSetting.cfg・AutoStarter.ini・libフォルダ・logフォルダをマウントしながら実行する.AutoStarter.iniは/home/aiwolf-platform/AutoStarter.iniとしてマウントする必要がある


6. 結論

完成には至らなかった

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