20210115のdockerに関する記事は10件です。

Jupyternotebookでpandas-profilingの日本語部分が文字化けする件について

はじめに

データ分析をする際に初めにやることといえば、データがどのような特徴を持っているのか把握することからだと思います。そんなときにpandas-profilingを使うとEDAを一括して行ってくれるのでとても便利です。しかし、Jupyternotebookで試したところデータの日本語のカラムなどが□□□のように文字化け(豆腐)となってしまったので解決策をまとめていきたいと思います。

環境

  • Python3.8
  • Docker
  • Jupyter notebook

原因

pandas-profilingで文字化けが起きる原因はmatplotlibseabornが日本語化対応できていないことに起因します。日本語化対応できれば、matplotlibとseabornを利用したpandas-profilingも日本語対応されます。

この記事ではmatplotlibseabornの日本語化の手順について説明することになります。

Matplotlibとseabornの日本語化

この記事ではDockerを利用したJupyternotebook環境の日本語対応について説明します。
さらに効率の良い方法があるかもしれませんので、その際にはコメントを頂けると嬉しいです。

1. 日本語のフォントをダウンロードする

こちらのサイトからipaexg00401.zip(4.0MB)をダウンロードして解凍します。
ipaexg00401フォルダの中にあるipaexg.ttfをDockerfileがあるディレクトリに移動します。

2. seabornの日本語対応のためコンテナ上のファイルをホストにコピーする

ここで行う作業は、seabornを日本語化させるために必要なrcmod.pyをローカルにダウンロードして内容を書き換え、docker-compose upの度に、コンテナ上のrcmod.pyをホストの書き換え済みのrcmod.pyで上書きするように設定します。このような流れをとることでdocker-compose upの度にrcmod.pyを書き換えずに済みます。

(本当はDockerfileでコンテナ上のを書き換えたいのですがわかりませんでした)

日本語対応していない状態でdocker-compose upをします。
別のターミナルを開いて、コンテナIDを確認します。

# コンテナIDを確認する
$ docker ps

次にコンテナ上のrcmod.pyをホスト(ローカル上)に保存します。

$ docker cp [コンテナID]:opt/conda/lib/python3.8/site-packages/seaborn/rcmod.py [保存先(C:\Users\....など)]

最後に保存したrcmod.pyをDockerfileがあるディレクトリにコピーします。

3. rcmod.pyを書き換える

rcmod.pyを開いて以下の内容を変更します。

86-87行目のdef set(context="notebook", ...)のfontの部分をfont="IPAexGothic"に変更します。

def set_theme(context="notebook", style="darkgrid", palette="deep",
              font="IPAexGothic", font_scale=1, color_codes=True, rc=None):

次に205行目の"font.family": ["sans-serif"]を以下に変更します

"font.family": ["IPAexGothic"]

これでseabornの日本語対応のための書き換えは終了です。

4. Dockerfileに以下を追加する

# matplotlibとscipyの日本語化
# 日本語のフォントをコピーする
COPY ipaexg.ttf /opt/conda/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/ipaexg.ttf
# 書き換えたrcmod.pyでコンテナ上のrcmod.pyを上書きする
COPY settings/localize_ja/rcmod.py /opt/conda/lib/python3.8/site-packages/seaborn/rcmod.py
# matplotlibの設定ファイルの最後にfont.family : IPAexGothicを追加する
RUN echo "font.family : IPAexGothic" >>  /opt/conda/lib/python3.8/site-packages/matplotlib/mpl-data/matplotlibrc
# キャッシュを削除する
RUN rm -r ./.cache

これでmatplotlibとseabornの日本語対応が行えます。
以下のコードで文字化けしないか確かめることができます。

# matplotlibが日本対応できているか確認する
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.xlabel('日本語化')
plt.ylabel('matplotlibの')
plt.show()
# seabornが日本語対応できているか確認する
import seaborn as sns
sns.set(style="whitegrid")

# Load the example Titanic dataset
titanic = sns.load_dataset("titanic")

# Draw a nested barplot to show survival for class and sex
g = sns.catplot(x="class", y="survived", hue="sex", data=titanic,
                height=6, kind="bar", palette="muted")
g.despine(left=True)
g.set_ylabels("seabornの日本語化")

ラベルに日本語が使われているので、ラベルが文字化け(豆腐)してなければ成功です。

matplotlibとseabornの日本語対応が確認出来たら、pandas-profilingでも日本語対応されているはずです。

終わりに

EDAを行う前にとりあえずpandas-profilingするのが定番になりそうな気がしています。

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

HeadlessCMSの「Strapi」をDockerで爆速で立ち上げてる

Strapiの公式のDockerイメージが用意されているのですが、そちらを使ってのStrapiの構築をやっている記事があまりなかったので記事にしました。

https://hub.docker.com/r/strapi/strapi

HeadlessCMSとは

記事を書いたり保存したりのバックエンドの機能だけを持っていて、記事を表示するフロント側の機能を持たないCMSのことです。

APIやGraphQLを用いてフロント側で記事を表示します。

メリットとしては、フロント側の技術は何を使ってもいいのでかなり自由度が高いことだと思います。

StrapiをDockerで起動する

StrapiをDockerで起動する設定について説明していきます。

docker-composeの設定

まずはdocker composeの設定からです。

$ mkdir strapi
$ cd strapi
$ vi docker-compose.yml
docker-compose.yml
version: '3'
services:
  strapi:
    image: strapi/strapi
    environment:
      DATABASE_CLIENT: mysql
      DATABASE_HOST: mysql
      DATABASE_PORT: 3306
      DATABASE_NAME: strapi
      DATABASE_USERNAME: strapi
      DATABASE_PASSWORD: strapi
      DATABASE_SSL: 'false'
    volumes:
      - ./app:/srv/app
    ports:
      - '1337:1337'
    depends_on:
      - mysql
    tty: true

  mysql:
    image: mysql
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - ./data:/var/lib/mysql
    ports:
    - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: strapi
      MYSQL_DATABASE: strapi
      MYSQL_USER: strapi
      MYSQL_PASSWORD: strapi
    cap_add:
      - SYS_NICE

以上でdockerの準備は終わりです。

StrapiをDockerで起動する

次にDockerでStrapiを起動していきます。

$ docker-compose up

これで起動は完了です。

注意点としては、以下の場所で10~15分程度止まります。
裏側で実行自体はされているので、終了などせずに待ってください。

strapi_1  | Starting your app...

Strapiの起動

以下が表示されたらStrapiの起動は完了です。

strapi_1  | Welcome back!
strapi_1  | To manage your project ?, go to the administration panel at:
strapi_1  | http://localhost:1337/admin
strapi_1  |
strapi_1  | To access the server ⚡️, go to:
strapi_1  | http://localhost:1337

Strapiでの記事作成

Strapiの記事作成までの使い方を説明していきます。

アカウントの作成

まずは http://localhost:1337/admin にアクセスします。

以下のようにアカウントの作成画面になるので、情報を入力してきます。
image.png

パスワードは大文字を含めないとアカウント作成できないので注意しましょう。

Strapiでの記事の作成の準備

Strapiでの記事の作成の準備をしていきます。

1.左のサイドバーのContent-Types Builder を選択

image.png

2.Create new collection type を選択

image.png

3.名前を入力して、「続ける」を押下

image.png

4.Title の設定

Textを選択します。
image.png

Nameは Title と打ち込んで Add another field を押下します。
image.png

5.次に先程と同じ要領で Rich Text を選択し、Nameには Text と入力して 「終了」を押下します

6.右上の「保存」を押下

image.png

サーバーのリスタートが始まるので、ターミナルで以下のように出たらページリロードしてください。

strapi_1  | Welcome back!
strapi_1  | To manage your project ?, go to the administration panel at:
strapi_1  | http://localhost:1337/admin
strapi_1  |
strapi_1  | To access the server ⚡️, go to:
strapi_1  | http://localhost:1337

記事の作成

記事の作成していきましょう。

1.サイドバーで作成した Articlesを選択します

image.png

2.Articlesを追加を押下

image.png

3.記事を書く

以下のように記事を書けます。
image.png

Title は先程追加したTextフィールド
Text はRich Textフィールドです。

Rich Textフィールドに関してはマークダウンで書いていくことができます。
他にも日付などのフィールドがあるので、必要なら使ってみてください。

4.保存をして公開

公開したらAPIで記事を配信できるようになります。

StrapiのAPIの使い方

StrapiでのAPIの使い方を説明してきます。

デフォルトだとAPIを叩いても以下のように権限で引っかかってしまったりするので少し設定が必要です。

GET http://localhost:1337/articles

image.png

権限設定の方法

サイドバーの設定 > ロールと権限 > Public の順に選択していきます。
image.png

以下のようにAPIで使いたい権限を選択します。
image.png

今回は記事の閲覧のみをしたいので find findone の2つにチェックを入れます。

右上のSave を選択して設定終了です。

APIを叩く

先程のAPIを叩くとちゃんと結果が返ってきます。

GET http://localhost:1337/articles

image.png

記事の詳細についても以下のようにAPIを叩けば返ってきます。

GET http://localhost:1337/articles/1

image.png

Strapiについてのまとめ

StrapiのDockerでの立ち上げ方と記事の作成方法、APIの設定の方法を説明しました。

簡単に記事の作成までをすることができるのでかなり便利なので試してみてください。

おかしなところや疑問点などありましたら、是非コメント下さい。

参考

https://strapi.io/documentation/developer-docs/latest/installation/docker.html#step-1-create-a-docker-compose-yaml-file

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

HeadlessCMSの「Strapi」をDockerで爆速で立ち上げる

StrapiのAPIの権限周りが分かりづらかったのと、公式のDockerイメージを使ってのStrapiの構築の情報があまりなかったので記事にしました。

https://hub.docker.com/r/strapi/strapi

HeadlessCMSとは

記事を書いたり保存したりのバックエンドの機能だけを持っていて、記事を表示するフロント側の機能を持たないCMSのことです。

APIやGraphQLを用いてフロント側で記事を表示します。

メリットとしては、フロント側の技術は何を使ってもいいのでかなり自由度が高いことだと思います。

StrapiをDockerで起動する

StrapiをDockerで起動する設定について説明していきます。

docker-composeの設定

まずはdocker composeの設定からです。

$ mkdir strapi
$ cd strapi
$ vi docker-compose.yml
docker-compose.yml
version: '3'
services:
  strapi:
    image: strapi/strapi
    environment:
      DATABASE_CLIENT: mysql
      DATABASE_HOST: mysql
      DATABASE_PORT: 3306
      DATABASE_NAME: strapi
      DATABASE_USERNAME: strapi
      DATABASE_PASSWORD: strapi
      DATABASE_SSL: 'false'
    volumes:
      - ./app:/srv/app
    ports:
      - '1337:1337'
    depends_on:
      - mysql
    tty: true

  mysql:
    image: mysql
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - ./data:/var/lib/mysql
    ports:
    - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: strapi
      MYSQL_DATABASE: strapi
      MYSQL_USER: strapi
      MYSQL_PASSWORD: strapi
    cap_add:
      - SYS_NICE

以上でdockerの準備は終わりです。

StrapiをDockerで起動する

次にDockerでStrapiを起動していきます。

$ docker-compose up

これで起動は完了です。

注意点としては、以下の場所で10~15分程度止まります。
裏側で実行自体はされているので、終了などせずに待ってください。

strapi_1  | Starting your app...

Strapiの起動

以下が表示されたらStrapiの起動は完了です。

strapi_1  | Welcome back!
strapi_1  | To manage your project ?, go to the administration panel at:
strapi_1  | http://localhost:1337/admin
strapi_1  |
strapi_1  | To access the server ⚡️, go to:
strapi_1  | http://localhost:1337

Strapiでの記事作成

Strapiの記事作成までの使い方を説明していきます。

アカウントの作成

まずは http://localhost:1337/admin にアクセスします。

以下のようにアカウントの作成画面になるので、情報を入力してきます。
image.png

パスワードは大文字を含めないとアカウント作成できないので注意しましょう。

Strapiでの記事の作成の準備

Strapiでの記事の作成の準備をしていきます。

1.左のサイドバーのContent-Types Builder を選択

image.png

2.Create new collection type を選択

image.png

3.名前を入力して、「続ける」を押下

image.png

4.Title の設定

Textを選択します。
image.png

Nameは Title と打ち込んで Add another field を押下します。
image.png

5.次に先程と同じ要領で Rich Text を選択し、Nameには Text と入力して 「終了」を押下します

6.右上の「保存」を押下

image.png

サーバーのリスタートが始まるので、ターミナルで以下のように出たらページリロードしてください。

strapi_1  | Welcome back!
strapi_1  | To manage your project ?, go to the administration panel at:
strapi_1  | http://localhost:1337/admin
strapi_1  |
strapi_1  | To access the server ⚡️, go to:
strapi_1  | http://localhost:1337

記事の作成

記事の作成していきましょう。

1.サイドバーで作成した Articlesを選択します

image.png

2.Articlesを追加を押下

image.png

3.記事を書く

以下のように記事を書けます。
image.png

Title は先程追加したTextフィールド
Text はRich Textフィールドです。

Rich Textフィールドに関してはマークダウンで書いていくことができます。
他にも日付などのフィールドがあるので、必要なら使ってみてください。

4.保存をして公開

公開したらAPIで記事を配信できるようになります。

StrapiのAPIの使い方

StrapiでのAPIの使い方を説明してきます。

デフォルトだとAPIを叩いても以下のように権限で引っかかってしまったりするので少し設定が必要です。

GET http://localhost:1337/articles

image.png

権限設定の方法

サイドバーの設定 > ロールと権限 > Public の順に選択していきます。
image.png

以下のようにAPIで使いたい権限を選択します。
image.png

今回は記事の閲覧のみをしたいので find findone の2つにチェックを入れます。

右上のSave を選択して設定終了です。

APIを叩く

先程のAPIを叩くとちゃんと結果が返ってきます。

GET http://localhost:1337/articles

image.png

記事の詳細についても以下のようにAPIを叩けば返ってきます。

GET http://localhost:1337/articles/1

image.png

Strapiについてのまとめ

StrapiのDockerでの立ち上げ方と記事の作成方法、APIの設定の方法を説明しました。

簡単に記事の作成までをすることができるのでかなり便利なので試してみてください。

おかしなところや疑問点などありましたら、是非コメント下さい。

参考

https://strapi.io/documentation/developer-docs/latest/installation/docker.html#step-1-create-a-docker-compose-yaml-file

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

【vscodeで xdebug3.0 × PHP × Docker】

【ディレクトリ構造】

.docker-practice
├── html
│   └─ arraypractice.php // デバックするファイル
├── php
│   ├── Dockerfile
│   └── php.ini
└── docker-compose.yml

【最終的なコードと設定】

docker-compose.yml

version: '2'
services:
    php:
     build: ./php
     ports:
        - '80:80'
     volumes:
        - ./html:/var/www/html
        - ./php/php.ini:/usr/local/etc/php/php.ini

同じ階層のphpディレクトリ内のDockerfile

FROM php:7.4-apache
# php.iniをdockerコンテナ内にコピって設置している
COPY php.ini /usr/local/etc/php/
# xdebugのinstallと設定に必要なzend_extensionを生成している
RUN pecl install xdebug \
  && docker-php-ext-enable xdebug
  # /usr/local/etc/php/conf.d/docker-php-ext-xdebug.iniに
  # zend_extension = ~ 出力される

php.iniにxdebug3.0の設定を追加

[xdebug]
xdebug.mode=debug
xdebug.start_with_request = yes
// host.docker.internalはdockerのhostマシンのIPを解決してくれる。
xdebug.client_host=host.docker.internal
xdebug.client_port=9003

vscodeのlaunch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9003,  // xdebug.client_portに合わせる
            "pathMappings": {
            // dockerコンテナ側ルートディレクトリ : vscode側ルートディレクトリ
                "/var/www/html": "${workspaceRoot}/html"
            }
        }
    ]
}

あとは./html直下のファイルにブレークポイントをつけて実行&ブラウザで読み込みすればbreakpointで止まってくれて、変数なんかもVARIABLESに表示される。
(21行目ではちゃんとksort後の$arrayが表示されている。)
800A6CDE-D918-45F0-A97C-D189623072C2.jpeg

【こういったコードになった経緯】

1,最初はdockerコンテナに入って、pecl install xdebug でxdebugをinstallしようとしたらphpのvarsionが7.2以上にするようにエラーが出たのでDockerfileのイメージを7.0→7.4にした。

2,とりあえずphpinfo()にxdebugの項目がでるようにしたかったが、
docker-php-ext-enable xdebugzend_extensin = ~ を作らないと表示されなかったので追加した。
また、buildしなおすたびにxdebugをinstallし直すのは面倒なのでDockerfileのRUNコマンドで実行できるようにした。

3,php.iniについては、 xdebug.start_with_request = yes がないとbreakpointで止まってくれなかった。

4,vscodeのlaunch.jsonは、pathMappingsは最初意味がわからず、
"./html" : "{workspaceRoot}" みたいにしてたが、dockerコンテナ側のルートディレクトリ : vscode側のワークスペースだとわかって変更。

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

VScodeからリモート先環境やリモート先のコンテナ環境で開発する方法

はじめに

VScodeを使ってリモート先の環境上で開発ができるとのことを聞いたので試してみた。

実行環境

【ローカルPC】
  ・Windows 10 pro
  ・VScode 1.50.1
  ・OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5

【リモート先の環境】
  ・Ubuntu 18.04 LTS(GCP上)
  ・docker 19.03.13
  ・python3系

手順

1.リモート先サーバのセットアップ
2.ローカルPCのパッケージ追加&設定編集
3.VScodeからリモート先ホストにSSH接続
4.VScodeからリモート先のコンテナ内にSSH接続

1.リモート先サーバのセットアップ

SSH鍵設定

GCP上のVMインスタンスにSSH接続できる様に設定
 【GCPのVMインスタンスにローカルPCからSSH接続】を参考に。
 ※鍵の生成はこのタイミングでしている。公開鍵はサーバー側にアップロード。秘密鍵は後で使う。

Pythonインストール

 ※VScodeからの接続後、リモート先の環境を使えているか確認するため

# python3系がインストールされているか確認
$ sudo python --version
$ sudo python3 --version

# python3系がなければ、以下を実行
$ sudo apt update
$ sudo apt install -y python3
$ sudo apt install -y python3-pip

Pythonパッケージのインストール

$ pip3 install numpy pandas beautifulsoup4
# ※pythonのパッケージは、後でチェックすることが目的なので、一応ローカルPCに入っていないパッケージを入れておく。

dockerのインストールとコンテナ作成

dockerのインストール
 【Dockerコンテナ内のUbuntuではsystemctlは使えない】の手順1を参考に。
 ※dockerのバージョンはdocker=ce=5:19.03.14~3-0~ubuntu-bionic

コンテナ環境にダイレクトにSSH接続するための鍵ペアを用意
 鍵の生成は最初の手順と同様。 ※ホストと同じ鍵でもいいが、今回は別途作成。

コンテナの作成

$ sudo docker container run -it -d -p 20022:22 --name test_con python:3

# コンテナに入ってパッケージをインストール
$ sudo docker container exec -it test_con /bin/bash
コンテナ内のコマンド
apt update 
apt install nano

# SSHの鍵設定
apt install -y openssh-server
mkdir /var/run/sshd
mkdir /root/.ssh/
nano /root/.ssh/authorized_keys
# ※公開鍵の中身をコピー

## pythonのパッケージインストール
pip install numpy pandas peewee

# SSHサーバ起動
/usr/sbin/sshd -D

2.ローカルPCのパッケージ追加&設定編集

VScodeを起動し、Remote - SSH をインストール

ローカルPCの.ssh/config ファイルの編集

Qiita-no025_img01.jpg

設定ファイルの中身は以下を参考に編集。

.ssh/config
Host gcp
 HostNameGCPの外部IPUserSSH接続するユーザー名】
 Port 【ポート番号】 ※記載がない場合、22番ポートとなる。
 IdentityFile 【秘密鍵までのパス】

コマンドプロンプト上からSSH接続できるか確認

コマンドプロンプト
> ssh gcp

# 恐らく、パスフレーズの入力を求められる。

※1)秘密鍵のアクセス制限が緩すぎるとエラーになる。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'C:\\Users\\秘密鍵までのパス' are too open.

※2)リモート先のPublickeyのアクセス権限が緩いと接続できない。[700] or [744] に設定しておく必要がある。

Permission denied, please try again.

3.VScodeからリモート先ホストにSSH接続

VScodeからSSH接続

Qiita-no025_img02.jpg

新しいウィンドウが開くので、そこでターゲットホストの OS カテゴリーでLinuxを速やかに選択する
Qiita-no025_img03.jpg
 ※初回の接続時、OSカテゴリー選択を行わないとCould not establish connection to .... となり接続できない。

bashからリモート先環境を利用できているか確認
 初めて接続した状態ではTERMINALが 1.install になっているため、『+』をクリックしbashを追加する。
Qiita-no025_img04.jpg
リモート先の環境をちゃんと利用できているか試しに確認

$ python3

>>> import numpy
>>> from bs4 imoprt BeautfulSoup

実行できればOK!

4.VScodeからリモート先のコンテナ内にSSH接続

ローカルPCの.ssh/config ファイルにコンテナの接続情報を追加

設定ファイルの中身は以下を参考に編集。

.ssh/config
Host gcp
 HostNameGCPの外部IPUserSSH接続するユーザー名】
 Port 【ポート番号】 ※記載がない場合、22番ポートとなる。
 IdentityFile 【秘密鍵までのパス】

Host gcp_container
 HostNameGCPの外部IPUserSSH接続するユーザー名】 ※今回は、コンテナ内にユーザー作成などしていないため [root]
 Port 【ポート番号】 ※ポートマッピングしたホスト側のポート番号(今回の場合だと20022IdentityFile 【秘密鍵までのパス】 ※上記のホストとは別の鍵

 ※一旦この段階で、コマンドプロンプトやTeraTermなどからのSSH接続を試す。

手順3と同じ様にVScodeからSSH接続を行い、コンテナの環境をちゃんと利用できているか確認
Qiita-no025_img05.jpg
接続完了後、TERMINALより以下を実行。

$ python

>>> import pandas 
>>> imoprt peewee

実行できればOK!

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

Dockerでハニーポット(Dionaea)を運用する

Dionaeaとは

マルウェアの収集を目的とした低対話型ハニーポット。
DinoTools/dionaea

ハニーポット構築

Dockerfile作成

Dockerfile
FROM ubuntu:18.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && \
    apt install -y --no-install-recommends \
    build-essential \
    cmake \
    check \
    cython3 \
    git \
    libcurl4-openssl-dev \
    libemu-dev \
    libev-dev \
    libglib2.0-dev \
    libloudmouth1-dev \
    libnetfilter-queue-dev \
    libnl-3-dev \
    libpcap-dev \
    libssl-dev \
    libtool \
    libudns-dev \
    less \
    python3 \
    python3-dev \
    python3-bson \
    python3-yaml \
    python3-boto3 \
    fonts-liberation && \
    apt autoremove -y && \
    git clone https://github.com/DinoTools/dionaea.git /opt/dionaea && \
    cd  /opt/dionaea && \
    mkdir build && \
    cd build && \
    cmake -DCMAKE_INSTALL_PREFIX:PATH=/opt/dionaea .. && \
    make && \
    make install && \
    groupadd --gid 1000 dionaea && \
    useradd -m --uid 1000 --gid 1000 dionaea && \
    chown -R dionaea:dionaea /opt/dionaea/var && \
    apt autoremove -y git

USER dionaea:dionaea

COPY dionaea.cfg /opt/dionaea/etc/dionaea/dionaea.cfg
COPY ftp.py /opt/dionaea/lib/dionaea/python/dionaea/
COPY index.html /opt/dionaea/var/lib/dionaea/http/root
COPY smbfields.py /opt/dionaea/lib/dionaea/python/dionaea/smb/include/
COPY mssql.py /opt/dionaea/lib/dionaea/python/dionaea/mssql/
COPY extras.py /opt/dionaea/lib/dionaea/python/dionaea/smb/

EXPOSE 21 42 69/udp 80 135 443 445 1433 1723 1883 1900/udp 3306 5060 5060/udp 5061 11211

Ubuntu 18.04をベースとしており、/opt/dionaea配下にインストールしています。
Docker Hubにイメージを公開しています。

dionaea.cfgの編集(loggingの部分のみ記載)

dionaea.cfg
[logging]
default.filename=var/log/dionaea/dionaea.log
default.levels=all,-debug
default.domains=*

errors.filename=var/log/dionaea/dionaea-errors.log
errors.levels=error
errors.domains=*

上記の設定により、dionaea.logはdebug以外のものを、dionaea-errors.logはerrorのみ出力するようになる。

/opt/dionaea/var/lib/dionaea/http/root/index.htmlの作成

/opt/dionaea/var/lib/dionaea/http/root/に何もないので、適当にindex.htmlを作成する。

Nmap対策

https://gist.github.com/steeve85/2902618
上記のURLを見れば分かるが、そのまま運用すると、Nmapでポートスキャンしたときにハニーポットだとバレてしまう。
バレないようにするために下記ファイルを編集する。

/opt/dionaea/lib/dionaea/python/dionaea/ftp.py(変更箇所だけ記載)
RESPONSE = {
    # -- 100's --
    "data_cnx_already_open_start_xfr":    "125 Data connection already open, starting transfer",
    "file_status_ok_open_data_cnx":       "150 File status okay; about to open data connection.",

    # -- 200's --
    "cmd_ok":                             "200 Command OK",
    "type_set_ok":                        "200 Type set to {mode}.",
    "entering_port_mode":                 '200 PORT OK',
    "sys_status_or_help_reply":           '211 System status reply',
    "dir_status":                         '212 %s',
    "file_status":                        '213 {value}',
    #"help_msg":                           '214 help: %s',
    "name_sys_type":                      '215 UNIX Type: L8',
    "welcome_msg":                        "220 Welcome to the ftp service",  ここの値を変更
    "svc_ready_for_new_user":             '220 Service ready',
    "goodbye_msg":                        '221 Goodbye.',

/opt/dionaea/lib/dionaea/python/dionaea/smb/include/smbfields.py(変更箇所だけ記載)
ConditionalField(UnicodeNullField(
            "OemDomainName", "WORKGROUP"), lambda x: not x.Capabilities & CAP_EXTENDED_SECURITY),
ConditionalField(UnicodeNullField(
            "ServerName", "HOMEUSER-3AF6FE"), lambda x: not x.Capabilities & CAP_EXTENDED_SECURITY),

「OemDomainName」と「ServerName」の値を変更する。

/opt/dionaea/lib/dionaea/python/dionaea/smb/extras.py(変更箇所だけ記載)
self.native_os = "Windows 5.1"
self.native_lan_manager = "Windows 2000 LAN Manager"
self.oem_domain_name = "WORKGROUP" ここの値を変更
self.os_type = 2
self.primary_domain = "WORKGROUP"
self.server_name = "HOMEUSER-3AF6FE" ここの値を変更
self.shares = {}
/opt/dionaea/lib/dionaea/python/dionaea/mssql/mssql.py(変更箇所だけ記載)
r.VersionToken.TokenType = 0x00 0x01に変更

コンテナ起動

docker run -itd --rm -p 21:21 -p 42:42 -p 69:69/udp -p 80:80 -p 135:135 -p 443:443 -p 445:445 -p 1433:1433 -p 1723:1723 -p 1883:1883 -p 1900:1900/udp -p 3306:3306 -p 5060:5060 -p 5060:5060/udp -p 5061:5061 -p 11211:11211 masaomi346/dionaea /opt/dionaea/bin/dionaea -u dionaea -g dionaea -c /opt/dionaea/etc/dionaea/dionaea.cfg
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose.ymlで複数コマンドを実行する方法

やりたいこと

docker-compose.ymlで下記のコマンドを実行したい

composer install --no-interaction
tail -f /dev/null

なぜDockerfileへ記載しないのか

リビルドが増え面倒

composer installはjsonの記載内容によってvendorにインストールされるものが変わる可能性がある
Dockerfileでcomposer installを実行する環境でコンテナ構築を行った場合、jsonを編集したらイメージから作り直しが必要になりとても面倒な為

ローカルディレクトリのマウント時に面倒が起こる

また、ローカルのディレクトリをコンテナにマウントさせている場合下記のようになる
イメージ作成→マウント→ローカルにはvendorディレクトリがない→マウント後、イメージ内にあるvendorが無くなる
※これが原因でどハマりした事あり

参考:
https://teratail.com/questions/203319

docker-compose.ymlへのコマンド記載方法(基本)

command: tail -f /dev/null

ちなみに上記コマンドは、普通にdocker-compose up -dしただけではコンテナのビルドのみで起動はされない(正確にはymlに記載の内容が全て実行終了した後コンテナが停止する)為、ymlに記載の内容が終了後も何かコマンドが実行されている状態ならコンテナが停止しない仕様からtail -fといった動作し続けるコマンドを実行することでコンテナが停止することを防いでいる

参考:
https://teratail.com/questions/280776

docker-compose.ymlへのコマンド記載方法(複数)

    command: >
      sh -c "
      composer install --no-interaction &&
      tail -f /dev/null
      "

番外編

dockerコンテナに入る時、bashだったりshだったりこの差がよくわかっていなかった為復習

shは、、

man sh

するとDASHというものが出てきた

dashとは、、

Debian Almquist shellの略で、bashよりも高速、らしい。
/bin/shの代替とも記載があったけど、なぜ代替しているのか、等深堀するのに時間がかかりそうなのでまた別の機会で。

https://ja.wikipedia.org/wiki/Debian_Almquist_shell

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

Building OpenPose (Pytorch_Realtime_Multi-Person_Pose_Estimation) environment on Docker : training part

過去の記事

PC上に学習環境を直接構築する方法は以下を参照
修正中

前提条件

ローカルマシンにGPUの環境が構築されている前提とします.
(nvidia-smiでGPUが確認できる)

Dockerのインストールは,以下のサイトなどを参考に...
https://qiita.com/ttsubo/items/c97173e1f04db3cbaeda

Dockerの基本操作

以下参照:
https://qiita.com/19503/private/a6f0d43c8cfc44748f62

Dockerコンテナを用いた環境構築

実行マシンのGPUやCUDAのバージョンに影響を受けないため,こちらのDockerコンテナを利用した方法を推奨します.

# 1.ホストPC上の操作
# setup COCO data(coco2017)
COCO_DIR=/home/your_work_dir/your_coco_data_dir
mkdir $COCO_DIR/images
cd $COCO_DIR/images
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
cd $COCO_DIR
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip

cd /home/your_work_dir
git clone https://github.com/pytorch/pytorch.git -b v0.2.0
cd pytorch
# Dockerfileを下(last-one-Docerfile)の様に編集
docker build -t last-one:v0.01 -f ./Dockerfile .
# --ipc="host"はホストPCとコンテナ間でメモリを共有するオプション,これが無いとメモリ不足により実行中に落ちる(以下参考)
# https://discuss.pytorch.org/t/unable-to-write-to-file-torch-18692-1954506624/9990
docker run --gpus all --ipc="host" -v /home/your_work_dir/your_coco_data_dir:/home/dat -itd --name last-one_cont last-one:v0.01
docker exec -it last-one_cont /bin/bash

# 2.Dockerコンテナでの操作

pip intall pycocotools
cd /home/dev/Pytorch_Realtime_Multi-Person_Pose_Estimation/preprocessing
COCO_DIR=/home/dat

apt-get update
pip install numpy==1.16.6 opencv-python==3.1.0.0 easydict==1.9

python generate_json_mask.py --ann_path $COCO_DIR/annotations/person_keypoints_train2017.json --json_path out/train2017_json.json --mask_dir out/train2017_maskdir --filelist_path out/train2017_filelst.txt --masklist_path out/train2017_masklst.txt
python generate_json_mask.py --ann_path $COCO_DIR/annotations/person_keypoints_val2017.json --json_path out/val2017_json.json --mask_dir out/val2017_maskdir --filelist_path out/val2017_filelst.txt --masklist_path out/val2017_masklst.txt

# if you encountered "import _tkinter # If this fails your Python may not be configured for Tk" error, you must install tk-dev as below
# apt-get update
# apt-get install tk-dev

# 関連ファイルのパスをviエディタで編集(以下例)
vi train2017_filelst.txt
%s/^/\/home\/dat\/images\/train2017\//g
vi val2017_filelst.txt
%s/^/\/home\/dat\/images\/val2017\//g
vi train2017_masklst.txt
%s/^/\/home\/dev\/Pytorch_Realtime_Multi-Person_Pose_Estimation\/preprocessing\//g
vi val2017_masklst.txt
%s/^/\/home\/dev\/Pytorch_Realtime_Multi-Person_Pose_Estimation\/preprocessing\//g

# --gpuオプションは自身のGPU環境によって変更が必要,かつ過去記事にしたがってtrain/train_pose.py l255のCUDA_VISIBLE_DEVICESを修正
TRAIN_DIR=/home/dev/Pytorch_Realtime_Multi-Person_Pose_Estimation/preprocessing/out
python train_pose.py --gpu 0 1 2 --train_dir $TRAIN_DIR/train2017_filelst.txt $TRAIN_DIR/train2017_masklst.txt $TRAIN_DIR/train2017_json.json --val_dir $TRAIN_DIR/val2017_filelst.txt $TRAIN_DIR/val2017_masklst.txt $TRAIN_DIR/val2017_json.json --config config.yml > $LOG


last-one-Docerfile
FROM nvidia/cuda:8.0-cudnn6-devel-ubuntu16.04

RUN echo "deb http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list

RUN apt-get update && apt-get install -y --no-install-recommends \
         build-essential \
         cmake \
         git \
         wget \
         vim \
         ca-certificates \
         libjpeg-dev \
         libpng-dev &&\
     rm -rf /var/lib/apt/lists/*

RUN wget https://repo.anaconda.com/archive/Anaconda2-2.4.0-Linux-x86_64.sh -O ./anaconda.sh && \
     chmod +x ./anaconda.sh && \
     ./anaconda.sh -b -p /opt/conda && \
     rm ./anaconda.sh && \
     /opt/conda/bin/conda install conda-build && \
     /opt/conda/bin/conda create -y --name pytorch-py27 python=2.7.13 numpy pyyaml scipy ipython mkl&& \
     /opt/conda/bin/conda clean -ya

ENV PATH /opt/conda/envs/pytorch-py27/bin:$PATH
RUN conda install --name pytorch-py27 -c soumith magma-cuda80
# This must be done before pip so that requirements.txt is available
WORKDIR /opt/pytorch
COPY . .

# install torch
RUN TORCH_CUDA_ARCH_LIST="3.5 5.2 6.0 6.1+PTX" TORCH_NVCC_FLAGS="-Xfatbin -compress-all" \
    CMAKE_PREFIX_PATH="$(dirname $(which conda))/../" \
    pip install -v .

# install torchvision
RUN git clone https://github.com/pytorch/vision.git -b v0.2.0
WORKDIR /opt/pytorch/vision
RUN pip install -v .

# clone OpenPose code
WORKDIR /home/dev
RUN git clone https://github.com/last-one/Pytorch_Realtime_Multi-Person_Pose_Estimation.git

# setup coco tools
RUN git clone https://github.com/cocodataset/cocoapi.git

RUN pip install pandas

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

Lambda Container Image を Java 15ベースで作ってみる

概要

AWS Lambdaがコンテナイメージをサポートしました。

コンテナイメージ作成には、AWSの提供しているベースイメージを使うのが手っ取り早いです。
が、2021/01/15現在、Java15は提供されていません。

私の参画しているプロジェクトでは現在Java15を採用しており、
11だと色々めんどくさいので15ベースでコンテナイメージを作れ! と言われ、
俺には無理だろ...と思いながら色々調べてやったら動いたので、共有します。

ソースコード

早速ですが成果物としてのソースコードを公開します。
多分動くと思います。

200 OK を返すだけのサンプルです。
intx24/java-15-lambda-container

Handlerの処理はほとんど awsdocs/aws-lambda-developer-guideのサンプル から拝借しています。
変更点として、Java15対応を確認するため、不要なswitch式を付け足しました。

どうやったか

1. まずJava11ベースイメージで動かしてみる

Java11のベースイメージを元に、まず動かしてみます。

ありがたいことに関連記事があったため、参考にして丸パクリし、Java11ベースのLambdaイメージを作成しました。
AWS LambdaのコンテナサポートをJavaで試してみた。

2. Java11ベースイメージDockerfileを見てみる

Java11ベースイメージのDockerfileを参考にしてみましょう」と上司に言われたので、見てみます。

よくわからない tar.xz を大量にADDしていることがわかります。
git lfs pull することで tar.xz ファイルが解凍可能になります。(最初これがわからなくて詰んだと思った)
以下、理解していったことを書いていきます

lambda-entrypoint.sh

DockerfileのENTRYPOINTです。

どうやら /var/runtime/bootstrap が実行されるらしいです。
${AWS_LAMBDA_RUNTIME_API} がない場合(多分ローカル環境)では エミュレータを使ってローカル実行を可能にしているっぽい。

エミュレータに関しては、Runtime support for Lambda container images
からダウンロード出来るので、これをローカルからコンテナにCOPYすれば良さそうです。

lambda-entrypoint.sh
#!/bin/sh
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.

if [ $# -ne 1 ]; then
  echo "entrypoint requires the handler name to be the first argument" 1>&2
  exit 142
fi
export _HANDLER="$1"

RUNTIME_ENTRYPOINT=/var/runtime/bootstrap
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
  exec /usr/local/bin/aws-lambda-rie $RUNTIME_ENTRYPOINT
else
  exec $RUNTIME_ENTRYPOINT
fi

/var/runtime/bootstrap

よくわからないファイルでした。
コンテナにコピペしても動かなかった & 中身がブラックボックス過ぎと判断したので、代替手段を探します。
どうやらカスタムランタイムを作る手順でbootstrapを作ればいけるらしい?

カスタムランタイムについて調べつつ、無理だから諦めようと思った頃に、
aws-lambda-java-runtime-interface-client でLambda関数が実行できることを知りました。
このコマンドを aws-lambda-rie の引数にすれば良さそうです。

3. 実装してみる

Dockerfile

Java15が入ってるAmazonLinux2のイメージがあるのでこれをベースにします。
後述する、自作の lambda-entrypoint.sh をENTRYPOINTとして,
Lambda関数 example.Handler::handleRequest を渡します。

FROM amazoncorretto:15

# set environment variables
ENV CLASSPATH /var/task/*

WORKDIR /var/task

# copy lambda execution files
COPY aws-lambda-rie /usr/local/bin/aws-lambda-rie
COPY lambda-entrypoint.sh /lambda-entrypoint.sh

# Copy function code
COPY build/libs/java-15-lambda-container-1.0-SNAPSHOT-all.jar /var/task/

# Set the Entrypoint
ENTRYPOINT ["/lambda-entrypoint.sh"]

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "example.Handler::handleRequest" ]

lambda-entrypoint.sh

aws-lambda-java-runtime-interface-client を実行します。
$HANDLER_NAME には、 Dockerfileの CMD で指定したLambda関数が渡されます。

aws-lambda-java-runtime-interface-client の README通りに java -cp ./* com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello を引数として渡すと、
aws-lambda-riejavabootstrap のあるパスだと解釈して死ぬため、/usr/bin/java に置き換えます。

また、ここではクラスパスをDockerfile内で環境変数として指定済みです。

#!/bin/sh

if [ $# -ne 1 ]; then
  echo "entrypoint requires the handler name to be the first argument" 1>&2
  exit 142
fi

HANDLER_NAME=$1

if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
  # local environment
  exec /usr/local/bin/aws-lambda-rie \
    /usr/bin/java \
    com.amazonaws.services.lambda.runtime.api.client.AWSLambda "$HANDLER_NAME"
else
  exec /usr/bin/java \
    com.amazonaws.services.lambda.runtime.api.client.AWSLambda "$HANDLER_NAME"
fi

/var/runtime/bootstrap

lambda-entrypoint.sh 内に統合したので不要となりました。

苦労したこと

javaのビルド周りがわからん

java自体の経験が1年ほど + intelliJ経由で触ってた + プロトタイプが出来ているプロジェクトに途中参画した 人間なので、
javaはgradleタスク実行したらとりあえず動くぐらいの認識でした。

そもそもクラスパスを通さなければ実行できないということも知らず, Class Not Found エラーで半日ほど消耗しました。
同じ原因で、カスタムランタイムのビルドについても1分で諦めました。

AWS提供のベースイメージをrun -it オプションでコンテナを探索できない

最初は ENTRYPOINT の概念すら知らなかったため、
各種ファイルを確認するため、 run -it でコンテナを探索しようと思ったら出来ず困ってました。
結果的には docker exec 経由で cat したり、
IntelliJのdocker のFilesタブで確認していました。

まとめ

今回、Lambda Container Image を Java 15ベースで作ってみて、一応動くところまで出来ました。

調査・実装含めて4日ほど作業にあてましたが、
まだまだ知るべきことが多くあるなと思わされる経験でした。

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

Docker for MacでLaravelを速くする方法

皆さんこんにちは。tyamahoriです。Docker for Mac使って開発してますか?遅くてキレ散らかしてませんか。。?

そんなあなたに朗報です。
2021年1月、tyamahoriはDocker for Mac が遅い問題に立ち向かいました。LaravelのサンプルプロジェクトをGitHubにあげておりますので見てください。

vendorディレクトリをそのままマウントしない!

composer install したら、vendorディレクトリができます。これをコンテナにマウントするさいに一工夫必要です。

じゃあどうするか?

ローカル開発だと、 docker-composeをほとんどの場合使うと思います。その際には、volumesを使うようにして、Macローカルにファイルを置かないようにします。

落とし穴。。

ただ、ローカルにvendorディレクトリがないと、PhpStormなどで補完が効きません。。いくらスピードが速くなるといえ、補完が聞かないと意味ないですよね。。。?

さらなる一工夫

コンテナ内でcomposerインストールをしたあとに、vendorディレクトリをMacのローカルに持ってきます。docker cp のコマンドがあるので、それを使って、コンテナないから、Macローカルにディレクトリをコピーします!

細かいところ

じゃあ、いつのタイミングでdocker cpやるのか? 新しくcomposer install でなにか追加した場合どうするのか。。などなどあります。そういうときは、スクリプトを組んで、色々と試行錯誤をしましょう。サンプルプロジェクトにスクリプトを置いてありますので、参考にしてみてください。

我慢するところ

docker cpでvendorディレクトリをMacローカルに持ってきたら、PhpStormはvendorディレクトリを読み込みます。その際にMacのファンがブンブン回るので、そこだけは我慢する必要があります。。

結論

本当に速くなるかはまず試してもらえればと思います。サンプルプロジェクトをクローンして、Docker for Macを使って、立ち上げて見てください!皆様のご感想お待ちしております!

GitHubでのプロジェクト

https://github.com/tyamahori/laravel8-sample

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