- 投稿日:2019-12-30T23:30:36+09:00
テストで使いたくて,DinD (Docker in Docker) でk8sの環境を整えた
TL;DR
- こちらのDockerfileを見納めください
- kindとアプリケーションのコンテナを分けても良かったのですが,kubeconfigの受け渡しが面倒だったので妥協しました
- https://github.com/tozastation/kw/blob/master/Dockerfile.test
事の経緯
- Kubernetesを制御するツールを書きたい.
- テストのために,KubernetesクラスタをホストPCに建てるの面倒だし,環境を汚したくない...
- kind (kubernetes in docker) なるものを発見
- しかし,アプリの開発をDocker内で行っていると,
kindとアプリのコンテナは同一ネットワークに参加していないため,ネットワーク的に参照できないという問題が
そこで,DinD (Docker in Docker)
クラスタの作成をホスト側でなく,コンテナ内のDockerで行うことによってネットワーク的に参照可能にする.
kind in DinD
docker:dind
というベースイメージがAlpineなので追加パッケージがある場合は,apk
を使います.- 使い方はこちらの記事が参考になります
FROM docker:dind RUN apk --no-cache add curl RUN curl -Lo /usr/local/bin/kind https://github.com/kubernetes-sigs/kind/releases/download/v0.6.1/kind-$(uname)-amd64 && chmod +x /usr/local/bin/kindkindでクラスタ作成 (Docker Deamonの起動を待つ必要あり)
以下をコンテナ内で実行すれば環境構築完了です!
# クラスタの作成 kind create cluster # KUBECONFIGに,作成したクラスタのkubeconfigパスを登録 export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"dindコンテナを立ち上げるときに詰まった点
- 問題
- docker run 時に,コマンドを渡すとdocker deamonが起動しなく,kindを実行できなかった
- 解決策
- docker run 実行後,execでコマンドを渡すようにする
まとめ
- kubernetesの環境構築は,minikubeなりkindが,Dockerで構築するオプションを提供してくれていて非常に便利だなと思いました.お試しで気軽に建てるときには自分も重宝しようと思います.
- DinDは初めて使いましたが,プロジェクトごとにDockerが作れるためホストから見たときのコンテナが散らからなくて管理しやすそうという印象です.
- Kubernetesアプリとかプロバイダー作っている世の方々はテスト用のクラスタ構築とかどうされているのかなと気になりました.
- 投稿日:2019-12-30T23:04:25+09:00
VS CodeでSSH先のDockerを開発環境に使う
前置き
VS Code
にRemote Development
が追加されしばらくが経ちました。
開発環境をDocker
に載せることで、別の端末やメンバー間で環境が手軽に統一できるのでメリットが大きいのですが、いくつか問題があるせいか利用してるところをあまり見たことがありません。ホストOSに
MacOS
を使っているとDocker
のファイルシステムの読み書きが遅くて、私はJavaScript
の開発を行うことが多いのですがnpm
周りのインストールやビルドがホストOS上で実行するのと比べ物にならないぐらい遅くなります。これは
Linux
上のDocker
がホストOSのカーネルを共有してるのに対し、MacOS
の場合はホストOSの上に軽量なDocker
の実行環境を載せて動かしているせいで、Docker
のコンテナ側でファイル変更する度にホストOSに通知される2重管理になってるせいのようです。
MacOS
の場合の対応はdocker-sync
を入れたり、cached
オプションを設定したり、いくつかあるのですが試してみた限りだとどれも多少早くはなるのですがあまり改善されないなって印象でした。今回の対応
根本的な解決はホストOSに
Linux
を用意するしかなさそうなので別マシンで用意しました。
私の場合はちょうど昔使っていたMac mini
があったのでArch Linux
を入れてDocker
用マシンにしました。
クラウド上に用意すればいつでも使える便利な環境が用意できると思います。
(そこまでするのは大掛かり過ぎるし、この記事に需要があるかは不明です)Dockerサーバ(Arch)の準備
SSH
接続できるLinux
端末を用意してDocker
のServer API
を設定します。vim /etc/systemd/system/docker-tcp.socketdocker-tcp.socket[Unit] Description=Docker Socket for the API [Socket] ListenStream=2375 BindIPv6Only=both Service=docker.service [Install] WantedBy=sockets.targetsystemctl enable docker-tcp.socket systemctl stop docker systemctl start docker-tcp.socket systemctl start docker
Dockerクライアント(MacOS)の準備
Docker
のCLI
をインストールします。
MacOS
上で動作するDocker
環境は要らないのでDocker for Mac
は入れずにHomebrew
からCLIだけをインストールします。Docker for Mac
が入ってる場合はそのままでも問題ないです。brew install docker
環境変数に
Docker
サーバの接続先を指定します。
任意のIPと上記のdocker-tcp.socket
で設定したポートを指定します。.zshrcexport DOCKER_HOST=tcp://192.168.2.2:2375
VS Code
の設定ファイルsetting.json
にDocker
サーバのSSH情報を設定します。setting.json"docker.host": "ssh://username@192.168.2.2"あとがき
これで
VS Code
のRemote Development
にDocker
サーバー上のコンテナが表示されて接続できるようになりました。
結果的にDocker
を動かす端末が別になったのですが環境を意識せずVS Code
とDocker CLI
をインストールするだけで環境が整うようになったのでアリなのかなと思います。参考
https://knowledge.sakura.ad.jp/2401/
https://code.visualstudio.com/docs/remote/containers-advanced
- 投稿日:2019-12-30T19:04:49+09:00
docker(89) dockerでpython2, python3
機械学習でpythonを使うのにanaconda3を利用してきた。
当方の機械学習の演習・ハッカソン等でWindowsでanaconda3を使うのに、うまく使えない人がいたので資料を作成した。
Windows(M.S.)にPython3(Anaconda3)を導入する(7つの罠)
https://qiita.com/kaizen_nagoya/items/7bfd7ecdc4e8edcbd679Windows(M.S.) にAnaconda3(python3)を 2019年版
https://qiita.com/kaizen_nagoya/items/c05c0d690fcfd3402534pythonで 言語処理100本ノック を実行するのには、必ずしもAnacondaである必要はないかもと思った。
docker(19) 言語処理100本ノックをdockerで。python覚えるのに最適。
https://qiita.com/kaizen_nagoya/items/7e7eb7c543e0c18438c4素のubuntuからpythonを導入する作業もしてみた。
macOS$ docker run -v /tmp/docker:/tmp/docker -it ubuntu /bin/bashubuntuが起動したら
# apt update; apt -y upgrade # apt install -y python2.7 python3.8 vim curl # curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py # python2.7 get-pip.py DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting pip Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) |################################| 1.4MB 1.9MB/s Collecting setuptools Downloading https://files.pythonhosted.org/packages/54/28/c45d8b54c1339f9644b87663945e54a8503cfef59cf0f65b3ff5dd17cf64/setuptools-42.0.2-py2.py3-none-any.whl (583kB) |################################| 583kB 4.0MB/s Collecting wheel Downloading https://files.pythonhosted.org/packages/00/83/b4a77d044e78ad1a45610eb88f745be2fd2c6d658f9798a15e384b7d57c9/wheel-0.33.6-py2.py3-none-any.whl Installing collected packages: pip, setuptools, wheel Successfully installed pip-19.3.1 setuptools-42.0.2 wheel-0.33.6 # pip install update Collecting update Downloading https://files.pythonhosted.org/packages/9f/c4/dfe8a392edd35cc635c35cd3b20df6a746aacdeb39b685d1668b56bf819b/update-0.0.1-py2.py3-none-any.whl Collecting style==1.1.0 Downloading https://files.pythonhosted.org/packages/4c/0b/6be2071e20c621e7beb01b86e8474c2ec344a9750ba5315886f24d6e7386/style-1.1.0-py2.py3-none-any.whl Installing collected packages: style, update Successfully installed style-1.1.0 update-0.0.1 # apt install python3-pip # pip3 install update Collecting update Cache entry deserialization failed, entry ignored Cache entry deserialization failed, entry ignored Downloading https://files.pythonhosted.org/packages/9f/c4/dfe8a392edd35cc635c35cd3b20df6a746aacdeb39b685d1668b56bf819b/update-0.0.1-py2.py3-none-any.whl Collecting style==1.1.0 (from update) Cache entry deserialization failed, entry ignored Cache entry deserialization failed, entry ignored Downloading https://files.pythonhosted.org/packages/4c/0b/6be2071e20c621e7beb01b86e8474c2ec344a9750ba5315886f24d6e7386/style-1.1.0-py2.py3-none-any.whl Installing collected packages: style, update Successfully installed style-1.1.0 update-0.0.1 # apt install python3-pip Reading package lists... 71% Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: binutils binutils-common binutils-x86-64-linux-gnu build-essential cpp cpp-7 dbus dh-python dirmngr dpkg-dev fakeroot g++ g++-7 gcc gcc-7 gcc-7-base gir1.2-glib-2.0 gnupg gnupg-l10n gnupg-utils gpg gpg-agent gpg-wks-client gpg-wks-server gpgconf gpgsm libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libapparmor1 libasan4 libassuan0 libatomic1 libbinutils libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdbus-1-3 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-7-dev libgdbm-compat4 libgdbm5 libgirepository-1.0-1 libglib2.0-0 libglib2.0-data libgomp1 libicu60 libisl19 libitm1 libksba8 liblocale-gettext-perl liblsan0 libmpc3 libmpfr6 libmpx2 libnpth0 libperl5.26 libpython3-dev libpython3-stdlib libpython3.6-dev libquadmath0 libstdc++-7-dev libtsan0 libubsan0 libxml2 linux-libc-dev make manpages manpages-dev netbase patch perl perl-modules-5.26 pinentry-curses python-pip-whl python3 python3-asn1crypto python3-cffi-backend python3-crypto python3-cryptography python3-dbus python3-dev python3-distutils python3-gi python3-idna python3-keyring python3-keyrings.alt python3-lib2to3 python3-minimal python3-pkg-resources python3-secretstorage python3-setuptools python3-six python3-wheel python3-xdg python3.6 python3.6-dev python3.6-minimal shared-mime-info xdg-user-dirs Suggested packages: binutils-doc cpp-doc gcc-7-locales default-dbus-session-bus | dbus-session-bus dbus-user-session libpam-systemd pinentry-gnome3 tor debian-keyring g++-multilib g++-7-multilib gcc-7-doc libstdc++6-7-dbg gcc-multilib autoconf automake libtool flex bison gdb gcc-doc gcc-7-multilib libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg libasan4-dbg liblsan0-dbg libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libmpx2-dbg libquadmath0-dbg parcimonie xloadimage scdaemon glibc-doc git bzr gdbm-l10n libstdc++-7-doc make-doc man-browser ed diffutils-doc perl-doc libterm-readline-gnu-perl | libterm-readline-perl-perl pinentry-doc python3-doc python3-tk python3-venv python-crypto-doc python-cryptography-doc python3-cryptography-vectors python-dbus-doc python3-dbus-dbg gnome-keyring libkf5wallet-bin gir1.2-gnomekeyring-1.0 python-secretstorage-doc python-setuptools-doc python3.6-venv python3.6-doc binfmt-support The following NEW packages will be installed: binutils binutils-common binutils-x86-64-linux-gnu build-essential cpp cpp-7 dbus dh-python dirmngr dpkg-dev fakeroot g++ g++-7 gcc gcc-7 gcc-7-base gir1.2-glib-2.0 gnupg gnupg-l10n gnupg-utils gpg gpg-agent gpg-wks-client gpg-wks-server gpgconf gpgsm libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libapparmor1 libasan4 libassuan0 libatomic1 libbinutils libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdbus-1-3 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-7-dev libgdbm-compat4 libgdbm5 libgirepository-1.0-1 libglib2.0-0 libglib2.0-data libgomp1 libicu60 libisl19 libitm1 libksba8 liblocale-gettext-perl liblsan0 libmpc3 libmpfr6 libmpx2 libnpth0 libperl5.26 libpython3-dev libpython3-stdlib libpython3.6-dev libquadmath0 libstdc++-7-dev libtsan0 libubsan0 libxml2 linux-libc-dev make manpages manpages-dev netbase patch perl perl-modules-5.26 pinentry-curses python-pip-whl python3 python3-asn1crypto python3-cffi-backend python3-crypto python3-cryptography python3-dbus python3-dev python3-distutils python3-gi python3-idna python3-keyring python3-keyrings.alt python3-lib2to3 python3-minimal python3-pip python3-pkg-resources python3-secretstorage python3-setuptools python3-six python3-wheel python3-xdg python3.6 python3.6-dev python3.6-minimal shared-mime-info xdg-user-dirs 0 upgraded, 105 newly installed, 0 to remove and 0 not upgraded. Need to get 109 MB of archives. After this operation, 356 MB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 liblocale-gettext-perl amd64 1.07-3build2 [16.6 kB] ... # # pip3 install update Collecting update Cache entry deserialization failed, entry ignored Cache entry deserialization failed, entry ignored Downloading https://files.pythonhosted.org/packages/9f/c4/dfe8a392edd35cc635c35cd3b20df6a746aacdeb39b685d1668b56bf819b/update-0.0.1-py2.py3-none-any.whl Collecting style==1.1.0 (from update) Cache entry deserialization failed, entry ignored Cache entry deserialization failed, entry ignored Downloading https://files.pythonhosted.org/packages/4c/0b/6be2071e20c621e7beb01b86e8474c2ec344a9750ba5315886f24d6e7386/style-1.1.0-py2.py3-none-any.whl Installing collected packages: style, update Successfully installed style-1.1.0 update-0.0.1参考資料(reference)
pip入門
https://qiita.com/kaizen_nagoya/items/50d8be773d6d59a58153
- 投稿日:2019-12-30T17:59:47+09:00
Apache Ambari でクラスタ構築
こちらの記事の続きになります。
Apache Ambari を Docker でインストールAmbari サーバーのコンテナにログインしているものとします。
事前準備
ssh のインストール
Ambari では各ノードへのアクセス時に ssh コマンドを使用するため、インストールしておきます。
(Docker イメージ作成時にインストールしておいた方がよかった)yum -y install openssh-server yum -y install openssh-clients # パスワードなしで接続できるようにしておきます ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key ssh-keygen -q -N "" -t rsa -f /root/.ssh/id_rsa cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys # ssh サービスを起動します systemctl start sshd.servicehttps://[hostname]:8440 is not reachable の回避
このままセットアップを続けていくと、Ambari でのクラスタの登録時に以下のようなエラーに出くわす可能性があります。
INFO 2019-MM-dd 02:07:50,730 NetUtil.py:70 - Connecting to https://host01.blueskyarea:8440/ca ERROR 2019-MM-dd 02:07:50,735 NetUtil.py:96 - EOF occurred in violation of protocol (_ssl.c:618) ERROR 2019-MM-dd 02:07:50,735 NetUtil.py:97 - SSLError: Failed to connect. Please check openssl library versions. Refer to: https://bugzilla.redhat.com/show_bug.cgi?id=1022468 for more details. WARNING 2019-MM-dd 02:07:50,736 NetUtil.py:124 - Server at https://host01.blueskyarea:8440 is not reachable, sleeping for 10 seconds...この状況を避けるため、以下の対応しておきます。
certificate validation の無効化vi /etc/python/cert-verification.cfg # -> verify=diable
2. ambari-agent のコンフィグ設定
vi /etc/ambari-agent/conf/ambari-agent.ini # -> [security] # force_https_protocol=PROTOCOL_TLSv1_2クラスタ構築を開始する
ambari サーバースタート
ambari サーバーをスタートします。
[root@host01 /]# ambari-server start Using python /usr/bin/python Starting ambari-server Ambari Server running with administrator privileges. Organizing resource files at /var/lib/ambari-server/resources... (中略)サインイン & Install Wizard 開始
起動後、http://[hostname or ipaddress]:8080/ にアクセスし、サインインします。
構築を開始します。"Launch Install Wizard" をクリックします。
クラスタ命名
好きなクラスタ名を付けます。(ここでは、MyCluster)
HDPバージョン選択
せっかくなので、ここで選べる最新版を選択します。
※そもそもインストールしたHDPのバージョンがこの執筆時点での最新ではないです
パブリックリポジトリからソフトウェアをインストールするため、"Use Public Repository"が選択されている状態で次に進みます。インストール対象サーバーのホスト名および、秘密鍵の設定
とりあえず、1台構成でチャレンジしてみたいと思います。
host01.blueskyarea
秘密鍵は直接貼り付けています。
エラー対応
ambari-agent のログを見てみると、サーバーへの接続に失敗しているようです。
# cat /var/log/ambari-agent/ambari-agent.log -> INFO 2019-MM-dd 13:14:10,449 NetUtil.py:70 - Connecting to https://host01.blueskyarea:8440/ca ERROR 2019-MM-dd 13:14:10,466 NetUtil.py:96 - EOF occurred in violation of protocol (_ssl.c:618) ERROR 2019-MM-dd 13:14:10,466 NetUtil.py:97 - SSLError: Failed to connect. Please check openssl library versions. Refer to: https://bugzilla.redhat.com/show_bug.cgi?id=1022468 for more details. WARNING 2019-MM-dd 13:14:10,466 NetUtil.py:124 - Server at https://host01.blueskyarea:8440 is not reachable, sleeping for 10 seconds...このエラーへの対策は、先に実施した ”certificate validation の無効化” で行ったはずですが、それだけでは足りなかったようです。
/etc/ambari-agent/conf/ambari-agent.ini を開き、[security]の項に以下の1行を追加します。[security] (中略) force_https_protocol=PROTOCOL_TLSv1_2ambari-agent を再起動します。
ambari-agent restart Restarting ambari-agent (中略)Retry Failed ボタンをクリックしてリトライさせると、今度は Success が出ました。
サービスの選択
インストールしたいサービスを選択します。
HDFS と YARN(+MapReduce2)だけ選択しましたが、Zookeeper と Ambari Metrics も必須ということで強制的に選択されました。Master のアサイン
これらのサービスの Master が1つのホスト(正確には Docker のコンテナ)にインストールされることになります。
※個人のローカルPCには負担が大きそうです
Slave and Client のアサイン
Slave と Client も1つのホストにインストールされることになります。
※ますます個人のローカルPCには負担が大きそうです
Customize Service
サービスによって、admin 用のパスワードの設定を要求されますので、適当に設定します。
Review
Review 画面が表示されますが、特に問題はなければ、Deploy ボタンをクリックします。
Install, Start and Test
完了までに一時間ほど掛かりました。
ダッシュボードが起動されました。
HDFS へのアクセス
HDFS にアクセスしてみます。
[root@host01 ~]# hdfs dfs -ls / Found 7 items drwxrwxrwx - yarn hadoop 0 2019-12-29 14:17 /app-logs drwxr-xr-x - yarn hadoop 0 2019-12-29 14:05 /ats drwxr-xr-x - hdfs hdfs 0 2019-12-29 14:06 /hdp drwxr-xr-x - mapred hdfs 0 2019-12-29 14:05 /mapred drwxrwxrwx - mapred hadoop 0 2019-12-29 14:07 /mr-history drwxrwxrwx - hdfs hdfs 0 2019-12-29 14:08 /tmp drwxr-xr-x - hdfs hdfs 0 2019-12-29 14:04 /userなんとか動作してくれているようです。
手間のかかる HDFS のインストールを Ambari を使用することで簡単に実現できました。
と言いたいところですが、Ambari のインストールからセットアップまでが個人的にはエラー続出で大変でした。
あと、PCスペックの懸念から、最小限のサービスしか起動していません。
本来の目的である HiveやSparkなどを試すことになった場合に果たして動作可能であるのか、引き続き試行していくつもりです。
- 投稿日:2019-12-30T16:55:36+09:00
DockerHubとGitHubを連携させる2019/12版
やりたいこと
- DockerHubとGitHubの連携
なぜこの記事を書いたか
- ネットに転がっている手順だと、「DockerHubのページの右上の”Create”から〜〜〜」というものしかなかった。
- 自分の環境だとWebでCreate Repositoryできなかった。
- 試しながらやりたいことができたので今後の備忘のために残しておく。
※DockerHubとGitHubの連携自体の詳細については参考URLのものを参考にしています。
環境
- macOS Catalina
- Chrome 79.0.3945.88
事前準備
- DockerHubからGitHubのアカウントを連携しておく。
https://hub.docker.com/settings/linked-accountsやったこと
- DockerHubのAccout SettingsのLinked AccountsからGitHubアカウントを連携
- Dockerfile作成
- Dockerfileからimageをbuild
- DockerHubにimageをpush
- GitHubにリポジトリ作成
- GitHubにDockerfileをpush
- DockerHubのリポジトリのページ(以下のURLの場所)の"Builds"を開く
https://hub.docker.com/repository/docker/[アカウント名]/[image名]
- GitHubを選択
- ブランチとかDockerfileの場所とかを設定
Source Type、Source、Docker Tag はあとから変更できない。確認
GitHubに変更をpushしてDockerHubが自動でBuildすることを確認する。
ビルド結果がSuccessになっていれば設定完了。参考URL
- 投稿日:2019-12-30T16:31:11+09:00
Dockerで始めるStackstorm再入門3/3(pythonスクリプトとmockを使ったテストコードを書く)
本記事はDockerで始めるStackstorm再入門1/3(環境構築からOrquestaで書いたWorkflowの結果をslackに通知する)の第3部です。
- Dockerで始めるStackstorm再入門1/3(環境構築からOrquestaで書いたWorkflowの結果をslackに通知する)
- Dockerで始めるStackstorm再入門2/3(条件分岐させるWorkflowと定期実行させるRuleを書く)
- Dockerで始めるStackstorm再入門3/3(pythonスクリプトとmockを使ったテストコードを書く)
0. 目次と構成図
- 1. Actionの実行スクリプトをshellscriptとpythonで書く場合の違い
- 2. pythonで書いたActionの実行スクリプトの書き方
- 3. mockでActionの実行スクリプトをテストする
- 4. Workflowで引数や結果に応じて分岐させる書き方(python-script編)
本記事では第2部で予告していたとおり、pythonでActionの実行スクリプト、より柔軟なworkflowの書き方についてお話していきます。
shellscriptでリモートリポジトリのステータスの確認とコンテナの再立ち上げを行いましたが、今度はそれをpythonでおこなってみます。
pythonでActionの実行スクリプトを書くと、shellscriptに比べてActionの返却値(return value)を柔軟に定義することができたり、mockを使ってテストコードも書くことができるので、よりきめ細かくActionを書くことができます。Dockerで始めるStackstorm再入門2/3(条件分岐させるWorkflowと定期実行させるRuleの書き方)より
本記事でお話する構成図
※1
Stackstormコンテナ内から同コンテナ外にあるアプリ(flask/nginx)コンテナに接続するために、
ホストのDockerデーモンのソケットファイル(var/run/docker.sock)
をマウントさせています。※2
Gtihubからリポジトリをcloneする際、ssh鍵やパスワードを使わずにおこなうべく、Personal access tokens
を使いました。
トークンの取得方法は下記の記事をご参照ください。
私はrepoをスコープとしてトークンを取得しました。参考
Creating a personal access token for the command line - GitHub Help1. Actionの実行スクリプトをshellscriptとpythonで書く場合の違い
Actionの成否判定として使えるものがshellscriptではリターンコードとstdout/stderrですが、
pythonでは、加えてrunメソッドの任意の返却値も使えます。
※シェルスクリプトでいうreturn_code
はpythonスクリプトでは、exit_code
と表記されています。
- local-shell-script (shellscript)
- return_code(0はActionのsuceeded, 0以外がfailed)
- stdout/stderr
- python-script
- exit_code(0はActionのsuceeded, 0以外がfailed)
- stdout/stderr
runメソッドの返却値
2. pythonで書いたActionの実行スクリプトの書き方
コードをひととおり確認したい方はGithubをご参照ください。
mydemo_pack/actions/scripts/git_status.pyおおむね書き方はpythonでプログラムを書く場合と同じですが、いくつかStackstorm独自の点があるので、そこだけ共有します。
- エントリーポイントは
runメソッド
- Actionの結果は
status
とexit_code
の他に任意のrunメソッドの返却値
で制御可能
- mydemo_packではdict型のresultを用意(write_resultメソッドで定義)
- __init__メソッドで
/opt/stackstorm/configs/*.yaml
を読み込み、self.configとして保持
- mydemo_packでは用意していないので実質不要
参考:
- Actions — StackStorm 3.1.0 documentation/opt/stackstorm/packs/mydemo_pack/actions/scripts/git_status.py#! /usr/bin/env python # -*- coding: utf-8 -*- import re import traceback from st2actions.runners.pythonrunner import Action from common_mydemo import Common class GitStatusAction(Action): """Action class for st2""" def __init__(self, config): self.config = config self.result = {} for r in [ "command", "branch", "expected", "bool", "stdout", "stderr" ]: self.result[r] = None self.common = Common() return (略) def check_stdout(self, branch, expected, stdout): success = False ptn = self._set_regex(branch, expected) for line in stdout: if not success and ptn.search(line): success = True else: pass return success, stdout (略) def write_result(self, command, branch, expected, bool, stdout, stderr): self.result.update({ "command": command, "branch": branch, "expected": expected, "bool": bool, "stdout": self._to_str(stdout), "stderr": self._to_str(stderr), }) return self.result def run(self, working_dir, branch, expected): """ Entrypoint for st2 """ bool = False command = '' stdout = [] stderr = [] try: # git fetchのコマンドを生成 cmd = self._git_fetch(working_dir, branch) # git fetchを実行するが、成否だけ知りたいのでself.common.execute_commandメソッドの返却値のstdout, stderrは_とし、明示的に不要とした bool, _, _ = self.common.execute_command(cmd) if bool: # git statusのコマンドを生成 command = self.set_command(working_dir) # git statusを実行し、bool==Trueである場合、stdoutの結果を後続のself.check_stdoutで判定 bool, stdout, stderr = self.common.execute_command(command) if bool: bool, stdout = self.check_stdout(branch, expected, stdout) self.result = self.write_result(command, branch, expected, bool, stdout, stderr) except: # try文のなかでエラーを引いた場合、tracebackモジュールでキャッチし、stderrに代入 stderr = traceback.format_exc() self.result = self.write_result(command, branch, expected, bool, stdout, stderr) #finally: # self.result = self.write_result(command, branch, expected, bool, stdout, stderr) return self.resultコマンドの実行はsubprocessモジュールを使って
actions/scripts/common_mydemo.py
としてまとめています。
こちらのpythonスクリプトは任意のActionのpythonスクリプトが内部的に呼ぶのでStackstormが認識する必要はないため、/opt/stackstorm/packs/mydemo_pack/*.yaml
のメタファイルを別途用意する必要もないです。/opt/stackstorm/packs/mydemo_pack/actions/scripts/common_mydemo.py#! /usr/bin/env python # -*- coding: utf-8 -*- import sys import traceback from subprocess import Popen, PIPE class Common: """ Common for mydemo """ def __init__(self): pass def execute_command(self, command): bool = False try: stdout, stderr = Popen( command, shell=True, stdout=PIPE, stderr=PIPE ).communicate() stdout = stdout.splitlines() stderr = stderr.splitlines() bool = True except: stdout = None stderr = traceback.format_exc() return bool, stdout, stderr3. mockでActionの実行スクリプトをテストする
サンプルのmydemo_packが手元にある方は
/opt/stackstorm/packs/mydemo_pack/tests/
の下にテストコードなどが用意されていることが確認できるはずです。root@$HOSTNAME:/# tree -L 3 /opt/stackstorm/packs/mydemo_pack/tests/ /opt/stackstorm/packs/mydemo_pack/tests/ ├── fixtures # runメソッドに渡す引数を定義 │ ├── git_status.yaml │ └── rebuild_app.yaml ├── git_status # mockオブジェクトに渡すsubmoduleメソッドの値のstdout/stderrを定義 │ └── response.yaml ├── rebuild_app # mockオブジェクトに渡すsubmoduleメソッドの値のstdout/stderrを定義 │ └── response.yaml ├── test_git_status.py # テストコード └── test_rebuild_app.py # 同上 3 directories, 7 filesmockを使わず、そのままテストコードからActionの実行スクリプトを走らせてみる
- 対象のテストコードは
/opt/stackstorm/packs/mydemo_pack/tests/test_git_status.py
- テストはStackstormが提供する
st2tests.base.BaseActionTestCase
を継承してTestGitStatusActionインスタンス
を生成して実行- 生成したActionインスタンスの直下に
action_cls = $CLASS
を書く
- e.g.
action_cls = GitStatusAction
- runメソッドに渡す引数は
/opt/stackstorm/packs/mydemo_pack/tests/fixtures/
内の任意のyamlで定義
- test_git_status.pyの場合は
/opt/stackstorm/packs/mydemo_pack/tests/fixtures/git_status.yaml
- テストの対象のActionインスタンスは以下のように生成
action = self.get_action_instance()
テストの実行コマンド
- st2-run-pack-tests -p \$PACKPATH
/opt/stackstorm/packs/tests/*.py
のテストコードを実行root@$HOSTNAME:/# st2-run-pack-tests -p /opt/stackstorm/packs/mydemo_pack
- st2-run-pack-tests -p \$PACKPATH -f \$TESTFILENAME
/opt/stackstorm/packs/tests/\$TESTFILENAME
を実行root@$HOSTNAME:/# st2-run-pack-tests -p /opt/stackstorm/packs/mydemo_pack \ > -f test_git_status
- st2-run-pack-tests -p \$PACKPATH -f \$TESTFILENAME:$METHOD
/opt/stackstorm/packs/tests/\$TESTFILENAMEの$METHOD
を実行root@$HOSTNAME:/# st2-run-pack-tests -p /opt/stackstorm/packs/mydemo_pack \ > -f test_git_status:TestGitStatusAction.test00_no_mock_st2参考:
Pack Testing — StackStorm 3.1.0 documentation Instantiating and obtaining class instancesテストコード
/opt/stackstorm/packs/mydemo_pack/tests/test_git_status.py#! /usr/bin/env python # -*- coding: utf-8 -*- from st2tests.base import BaseActionTestCase from mock import MagicMock, patch import json import yaml import os import sys import re BASE_DIR = '/opt/stackstorm/packs/mydemo_pack' sys.path.append(BASE_DIR) sys.path.append(BASE_DIR + '/actions/scripts') sys.path.append('/opt/stackstorm/virtualenvs/mydemo_pack/lib/python2.7/site-packages') sys.path.append('/opt/stackstorm/st2/lib/python2.7/site-packages') input_file = "git_status.yaml" res_file = BASE_DIR + "/tests/git_status/response.yaml" from git_status import GitStatusAction class TestGitStatusAction(BaseActionTestCase): # テスト対象のActionの実行スクリプトのclass名を書く action_cls = GitStatusAction def test00_no_mock_st2(self): input = yaml.load( self.get_fixture_content(input_file), Loader=yaml.FullLoader ) # Actionインスタンスを生成 action = self.get_action_instance() # runメソッドを実行 result = action.run(**input) print('result: {r}'.format(r=result)) self.assertEquals(len(result), 6) self.assertEqual(result["bool"], True)runメソッドの引数が書かれた\$PACK/tests/fixtures/*.yaml
/opt/stackstorm/packs/mydemo_pack/tests/fixtures/git_status.yaml"working_dir": "/usr/src/app/flask-docker" "branch": "devel-views" "expected": "up_to_date"mockを使って、任意のメソッドの返却値を書き換える
/opt/stackstorm/packs/mydemo_pack/tests/test_git_status.py#! /usr/bin/env python # -*- coding: utf-8 -*- from st2tests.base import BaseActionTestCase from mock import MagicMock, patch import json import yaml import os import sys import re BASE_DIR = '/opt/stackstorm/packs/mydemo_pack' sys.path.append(BASE_DIR) sys.path.append(BASE_DIR + '/actions/scripts') sys.path.append('/opt/stackstorm/virtualenvs/mydemo_pack/lib/python2.7/site-packages') sys.path.append('/opt/stackstorm/st2/lib/python2.7/site-packages') input_file = "git_status.yaml" res_file = BASE_DIR + "/tests/git_status/response.yaml" from git_status import GitStatusAction class TestGitStatusAction(BaseActionTestCase): action_cls = GitStatusAction (略) # mockオブジェクトで書き換えるメソッド @patch("common_mydemo.Common.execute_command") def test01_mock_st2(self, execute): input = yaml.load( self.get_fixture_content(input_file), Loader=yaml.FullLoader ) def _execute_command(_cmd): bool = True #stdout = ["Your branch is up-to-date with 'origin/devel-views'"] #stderr = [""] # yamlからstdout/stderrの値を取得 res = yaml.load(open(res_file), Loader=yaml.FullLoader) stdout = res["succeeded"]["up_to_date"]["stdout"] stderr = res["succeeded"]["up_to_date"]["stderr"] return bool, stdout, stderr # _execute_commandメソッドの値をside_effectに代入 execute.side_effect = _execute_command # actionインスタンスを生成し、runメソッドを実行 action = self.get_action_instance() result = action.run(**input) print('result: {r}'.format(r=result)) self.assertEquals(len(result), 6) self.assertEqual(result["bool"], True) self.assertEqual( result["command"], "cd /usr/src/app/flask-docker && sudo git status" ) ans = yaml.load(open(res_file), Loader=yaml.FullLoader) self.assertEqual( result["stdout"], '\n'.join(map(str, ans["succeeded"]["up_to_date"]["stdout"])) ) self.assertEqual( result["stderr"], '\n'.join(map(str, ans["succeeded"]["up_to_date"]["stderr"])) ) @patch("common_mydemo.Common.execute_command") def test02_mock_st2_not_up_to_date(self, execute): input = yaml.load( self.get_fixture_content(input_file), Loader=yaml.FullLoader ) # runメソッドの引数の値はテストコードのなかで書き換える input.update({ 'expected': 'not_up_to_date' }) def _execute_command(_cmd): bool = True #stdout = ["Your branch is up-to-date with 'origin/devel-views'"] #stderr = [""] res = yaml.load(open(res_file), Loader=yaml.FullLoader) stdout = res["succeeded"]["not_up_to_date"]["stdout"] stderr = res["succeeded"]["not_up_to_date"]["stderr"] return bool, stdout, stderr execute.side_effect = _execute_command action = self.get_action_instance() result = action.run(**input) print('result: {r}'.format(r=result)) self.assertEquals(len(result), 6) self.assertEqual(result["bool"], True) self.assertEqual( result["command"], "cd /usr/src/app/flask-docker && sudo git status" ) ans = yaml.load(open(res_file), Loader=yaml.FullLoader) self.assertEqual( result["stdout"], '\n'.join(map(str, ans["succeeded"]["not_up_to_date"]["stdout"])) ) self.assertEqual( result["stderr"], '\n'.join(map(str, ans["succeeded"]["not_up_to_date"]["stderr"])) )※異常処理の動作確認
def _execute_command(_cmd): raise Exception("err_message") execute.side_effect = _execute_command/opt/stackstorm/packs/mydemo_pack/tests/git_status/response.yaml"succeeded": "up_to_date": "stdout": - "'On branch devel-views'" - "Your branch is up-to-date with 'origin/devel-views'." - "''" - "'nothing to commit, working directory clean'" "stderr": - "" "not_up_to_date": "stdout": - "hoge" "stderr": - "" "failed": "up_to_date": "stdout": - "" "stderr": - "" "not_up_to_date": "stdout": - "" "stderr": - "hoge"4. Workflowで引数や結果に応じて分岐させる書き方(python-script編)
- 基本的には引数の値に応じて分岐させるときと同じだが、
boolean値やintegerのときはstringに型変換
する必要がある
- 値そのものは
result().$RETURN_VALUE
で取得できるnext: - when: <% str(result().result.bool) = "true" %>
- Actionの返却値を次のAction以降で使うために変数化(publish)する方法
next: - when: <% succeeded() and str(result().result.bool) = "true" and (ctx().expected = 'up_to_date') %> do: last publish: - bool: <% result().result.bool %> - commnad: <% result().result.command %> - expected: <% result().result.expected %> - stdout: <% result().result.stdout %> - stderr: <% result().result.stderr %>
- 値を複数行に分けて書く方法
key: |- val1 <% result().result.val1 %> val2 <% result().result.val2 %>Workflow全体
/opt/stackstorm/packs/mydemo_pack/actions/workflows/poll-repo-python.yamlversion: 1.0 description: poll remote repo input: - working_dir - branch - expected - ptns - timeout output: - failed: <% ctx().failed %> - action_name: <% ctx().action_name %> tasks: init: # failedフラグを初期化(False)とするだけのAction action: core.noop next: - publish: - failed: False - action_name: 'poll-repo-python' do: git_status_before_merged git_status_before_merged: # ローカルリポジトリは最新であることを想定してgit status action: mydemo_pack.git_status_python input: working_dir: <% ctx().working_dir %> branch: <% ctx().branch %> expected: <% ctx().expected %> #デフォルト値は'up_to_date' timeout: <% ctx().timeout %> next: # ローカルリポジトリは最新であることが確認できた - when: <% succeeded() and str(result().result.bool) = "true" and (ctx().expected = 'up_to_date') %> do: last publish: - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [expected] <% result().result.expected %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> # ローカルリポジトリは最新ではないことが確認できた - when: <% succeeded() and str(result().result.bool) = "true" and (ctx().expected = 'not_up_to_date') %> do: git_merge publish: - failed: False - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [expected] <% result().result.expected %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> # ローカルリポジトリは最新であることが確認できなかった - when: <% succeeded() and str(result().result.bool) = "false" and (ctx().expected = 'up_to_date') %> do: git_status_before_merged publish: - failed: True - expected: 'not_up_to_date' - when: <% failed() %> do: post_msg publish: - failed: True - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [expected] <% result().result.expected %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> git_merge: # git_status_before_mergedで、ローカルリポジトリは最新ではないことが確認出来きた場合のみ実行 action: core.local input: cmd: sudo git merge origin/<% ctx().branch %> cwd: <% ctx().working_dir %> timeout: <% ctx().timeout %> next: - when: <% succeeded() %> do: git_status_after_merged publish: - expected: 'up_to_date' - when: <% failed() %> do: post_msg publish: - failed: True - action_result: |- [result] <% result() %> git_status_after_merged: # ローカルリポジトリは最新であるとしてgit_status_after_mergedを実行 action: mydemo_pack.git_status_python input: working_dir: <% ctx().working_dir %> branch: <% ctx().branch %> expected: 'up_to_date' timeout: <% ctx().timeout %> next: - when: <% succeeded() and str(result().result.bool) = "true" %> do: rebuild_app publish: - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [expected] <% result().result.expected %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> - when: <% failed() %> do: post_msg publish: - failed: True - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [expected] <% result().result.expected %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> rebuild_app: # コンテナが既に立ち上がっていれば、停止/削除し、再立ち上げを図る action: mydemo_pack.rebuild_app_python input: working_dir: <% ctx().working_dir %> ptns: <% ctx().ptns %> timeout: <% ctx().timeout %> next: - when: <% succeeded() and str(result().result.bool) = "true" %> do: post_msg publish: - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> - when: <% failed() or str(result().result.bool) = "false" %> do: post_msg publish: - failed: True - action_result: |- [bool] <% result().result.bool %> [commnad] <% result().result.command %> [stdout] <% result().result.stdout %> [stderr] <% result().result.stderr %> post_msg: action: slack.post_message input: message: |- [action_name] <% ctx().action_name %> [failed] <% ctx().failed %> [action_result] <% ctx().action_result %> next: - do: last last: action: core.noop next: - when: <% ctx().failed %> do: fail参考
orqeustaのサンプルコード
テストコード
本記事で扱ったStackstormのサンプルコード
Stackstormの管理対象のアプリコンテナ
ActionとWorkflowのサンプルコード
P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)
- 投稿日:2019-12-30T15:52:42+09:00
DockerとSquidを用いて、テスト用の認証プロキシサーバを構築する
ここ数回、UiPath製品群をプロキシ環境内で運用する手順を整理しています。
- UiPath製品群をプロキシ環境で使用するための環境設定(UiPath Enterprise版/認証なしプロキシのケース)
- UiPath製品群をプロキシ環境で使用するための環境設定(UiPath Community版/認証なしプロキシのケース)
残るは認証プロキシーを越える件を整理したいのですが、認証プロキシっていわゆる業務環境やお客さま環境にしかなかったりして、テストがしづらいです。ということで手元に「認証プロキシ」があればなーってことで、今回は「認証プロキシ」自体の構築手順を整理しました。
具体的には、
- 仮想マシンを立ち上げるための Vagrant を用いてLinux環境を構築
- そのLinuxにDockerをインストール
- そのDocker上に、OSSのプロキシサーバ「Squid」のコンテナを構築
- そのコンテナ上で、SquidのForward Proxy の機能で認証プロキシを設定
となります。書くと長いですが、Vagrantで構築はワンタッチです :-) 便利な世の中です。
この記事の対象の方
- 顧客環境でテストができないので、手元に認証プロキシサーバが欲しいヒト
- 自宅のネット環境を認証プロキシ経由にしたいヒト :-)
あ、ちなみにコレで構築した認証プロキシは性能やセキュリティなどは考慮しておりませんのでご注意ください1。あくまでテスト環境ということで。
前提
一応 MacのVagrantで構築しますが、最終的にはDockerなので環境はなんでもダイジョブかと。また最後に、Dockerでなく通常のUbuntu Linuxへの構築手順も記載しておきます。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.2 BuildVersion: 19C57 $ vagrant --version Vagrant 2.0.4 $Vagrant上のDockerにSquidのコンテナをたてる
GitHubから、Vagrantfileなど設定情報を取得
$ git clone https://github.com/masatomix/environment_template.git $ cd environment_template $ cat Vagrantfile .. .. config.vm.provision :shell, :path => "./script/provision_docker_squid.sh",:privileged => false $↑デフォルトではSquidのコンテナ構築は無効にしてあるので、アンコメントして有効にします。
VagrantでUbuntu Linux環境構築、Dockerその他もインストール。その後 sshログイン
$ vagrant up ... いろいろインストールで結構時間がかかる、、、 $ vagrant ssh Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-154-generic x86_64) *** System restart required *** Last login: Sun Dec 29 21:15:59 2019 from 10.0.2.2 vagrant@ubuntu-xenial:~$IPアドレス 確認
構築したLinuxのアドレスが、プロキシサーバのIPアドレスになります。下記の
192.168.xx.xx
にあるアドレスをメモっておきましょう。vagrant@ubuntu-xenial:~$ /sbin/ifconfig .. enp0s8 Link encap:イーサネット ハードウェアアドレス xxx inetアドレス:192.168.xx.xx ブロードキャスト:192.168.xx.255 マスク:255.255.255.0起動確認・停止・起動
構築が正しく行われていると、Docker上のSquidはすでに起動しているはずです。
vagrant@ubuntu-xenial:~$ cd /vagrant/squid/ vagrant@ubuntu-xenial:/vagrant/squid$ 起動確認 vagrant@ubuntu-xenial:/vagrant/squid$ sudo docker-compose ps Name Command State Ports --------------------------------------------------------------------------------- squid_squid_1_d48da617dc4d /sbin/entrypoint.sh Up 0.0.0.0:3128->3128/tcp ← Stateが'Up'ならOK 停止 vagrant@ubuntu-xenial:/vagrant/squid$ sudo docker-compse down 起動 vagrant@ubuntu-xenial:/vagrant/squid$ sudo docker-compse up -d疎通確認しましょう。インターネットオプションにプロキシとして上記の
http://[IPアドレス]:3128
を指定して、ネットへアクセスしてみましょう。
プロキシ認証画面がでればOKです。 あらかじめおいてあるユーザ情報ファイル.htpasswd
にはID/Passがuser01/user01で登録されているので、プロキシ認証画面に入力してみてください。
もしくは
curl
などで、$ curl https://qiita.com/ -x http://user01:user01@192.168.xx.xx:3128 -Iとうってみて、
HTTP/2 200
などの応答が返ってくればOKです。構築した環境の稼働確認は以上です。
ユーザの作成
今回はテスト環境なのでユーザの追加などは不要かもしれませんが、認証プロキシのユーザを追加したいときは以下のコマンドで。
vagrant@ubuntu-xenial:/vagrant/squid$ sudo htpasswd /vagrant/squid/.htpasswd user02構築した環境の設定
Docker上に構築したSquidコンテナの設定ファイル
xx
や、Squid自体の設定ファイルsquid.conf
は以下の通りに設定してあります。まずは
docker-compose.yml
。vagrant@ubuntu-xenial:~$ cat /vagrant/squid/docker-compose.ymldocker-compose.ymlversion: '2' services: squid: image: sameersbn/squid:3.5.27-2 ports: - "3128:3128" volumes: - /srv/docker/squid/cache:/var/spool/squid - ./squid.conf:/etc/squid/squid.conf - ./.htpasswd:/etc/squid/.htpasswd restart: alwaysつづいて
squid.conf
。vagrant@ubuntu-xenial:~$ cat /vagrant/squid/squid.confsquid.confacl SSL_ports port 443 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 # https acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl CONNECT method CONNECT http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access allow localhost manager http_access deny manager #http_access allow all #http_access allow localhost #http_access deny all http_port 3128 coredump_dir /var/spool/squid refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880 refresh_pattern . 0 20% 4320 auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid/.htpasswd auth_param basic children 5 auth_param basic realm Squid Basic Authentication (user:[user01]/pass:[user01]) auth_param basic credentialsttl 2 hours auth_param basic casesensitive off acl pauth proxy_auth REQUIRED http_access allow pauth no_cache deny all forwarded_for off request_header_access Referer deny all request_header_access X-FORWARDED-FOR deny all request_header_access Via deny all request_header_access Cache-Control deny all logformat mycombined %>a %[ui %[un [%tl] "%rm %>ru HTTP/%rv" %>Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh access_log daemon:/var/log/squid/access.log mycombined $おつかれさまでした。
参考:Linux上にインストール
コンテナでなくLinuxへ直接Squidを入れたい場合の手順を記しておきます。
Ubuntu 16.04.6 LTS (Xenial Xerus) の例。$ sudo apt install -y squid $ sudo apt install -y apache2-utils $ sudo htpasswd -c /etc/squid/.htpasswd user01でパスワードファイルまでつくっておきましょう。
設定ファイルsquid.conf
は上記GitHubにあるモノそのままを/etc/squid/squid.conf
へ配置してください。あとは起動・停止コマンド。
$ sudo systemctl status squid ● squid.service - LSB: Squid HTTP Proxy version 3.x Loaded: loaded (/etc/init.d/squid; bad; vendor preset: enabled) Active: active (running) since 日 2019-12-29 21:44:26 JST; 11min ago Docs: man:systemd-sysv-generator(8) Process: 2043 ExecStop=/etc/init.d/squid stop (code=exited, status=0/SUCCESS) Process: 2079 ExecStart=/etc/init.d/squid start (code=exited, status=0/SUCCESS) Tasks: 5 Memory: 21.1M CPU: 568ms CGroup: /system.slice/squid.service ├─2119 /usr/sbin/squid -YC -f /etc/squid/squid.conf ├─2121 (squid-1) -YC -f /etc/squid/squid.conf ├─2122 (logfile-daemon) /var/log/squid/access.log ├─2123 (pinger) └─2127 (basic_ncsa_auth) /etc/squid/.htpasswd 12月 29 21:44:26 ubuntu-xenial systemd[1]: Starting LSB: Squid HTTP Proxy version 3.x... 12月 29 21:44:26 ubuntu-xenial squid[2079]: * Starting Squid HTTP Proxy squid 12月 29 21:44:26 ubuntu-xenial squid[2119]: Squid Parent: will start 1 kids 12月 29 21:44:26 ubuntu-xenial squid[2079]: ...done. 12月 29 21:44:26 ubuntu-xenial systemd[1]: Started LSB: Squid HTTP Proxy version 3.x. 12月 29 21:44:26 ubuntu-xenial squid[2119]: Squid Parent: (squid-1) process 2121 started 停止 $ sudo systemctl stop squid 起動 $ sudo systemctl start squidおつかれさまでした。
関連リンク
- UiPath製品群をプロキシ環境で使用するための環境設定(UiPath Enterprise版/認証なしプロキシのケース)
- UiPath製品群をプロキシ環境で使用するための環境設定(UiPath Community版/認証なしプロキシのケース)
- sameersbn/squid:3.5.27-2
- Squid
- Vagrant
- Docker
- Squidでプロキシ(Basic認証)の設定
認証プロキシ経由でのみネット接続可能にするには、そもそもプロキシ経由以外のネット接続を遮断するなど、ネットワークレベルでの制御が必要ですしね。。 ↩
- 投稿日:2019-12-30T15:23:17+09:00
vscodeと開発環境をdockerにまとめてみた(2019年版)
[記事の概要]
- 取ってきたらX転送でVisual Studio Codeが試せる環境。
- ubuntu:18.04をベース
- Visual Studio Codeインストール済み
- X転送設定済み
- 日本語入力(Mozc)設定済み
- chromeも入っているヨ
- これを下地にVsCode+デバッグ環境構築済みの環境とかも作れると思う。
- X転送over sshなので、通常に使うよりもかなり高スペックが必要です。
はじめに
2018年に同様の内容の記事を書きました。
少しするとVSCode側の問題から日本語入力が出来なくなっていました...。
今回はそのあたりにも対応しました。
準備(Windows 10)
Docker for windows
説明は不要かと思います。
入れてください。VcXsrv
Windows上で動作するXサーバです。
インストールに関して特に難しい事は無いので、以下サイトが参考になります。なお、お金を使って良い人はX410が本当にインストールするだけで動くのでお勧めです。
putty
sshクライアントです。
実際は何でもよいのですが、色々と試した結果、VcXsrvとの相性が一番良かったのがこれだったので推奨します。
(最初はCygwinのsshでX転送していたけど、上手く動く時とそうでない時があり原因が良くわからなかったため...。)
使い方
docker image取得
docker huubからイメージを取得します。
docker pull yamada28go/docker-x-japanese-vscode-base:ubuntu_18.04-lts
docker 起動
取ってきたイメージを起動します。
起動コマンドの実行例は以下です。[コマンド例]
docker run --rm -p 23001:22 --shm-size=512m --name VsCodeTest yamada28go/docker-x-japanese-vscode-base:ubuntu_18.04-lts
[意味]
- sshポートをローカルポートの23001に転送
- 停止したらコンテナ消去
- コンテナ名は「VsCodeTest」
- プロセス間の共有メモリは512mbytechromeを使用する場合、「--shm-size=512m」は重要なオプションとなります。
何も設定しない状態のdockerの場合、この共有メモリ領域が極端に小さいため、メモリが不足してchromeが安定しません。[参考]
Dockerコンテナ上のChromeの動きが悪い時の対応方法VcXsrvの起動
Xサーバを先に起動します。
普通に起動すれば使えますが、設定に関して質問が出てきます。
設定方法は上の参考リンクを参照してください。puttyの設定
puttyから接続します。
何か所か設定が必要なので、以下説明します。
- 接続ポート
コンテナ起動時に指定したポートを指定します。
- X転送の有効化
X転送の有効化をします。
puttyからの接続
設定が出来たら接続します。
ログイン情報は以下です。
ユーザー名 パスワード 備考 dev dev ←こっちを使う root hoge 管理者用 接続するとX転送が有効な状態となっています。
puttyから「xeyes」と入力するとお馴染みの目玉が出てきます。
「code」と入力するとVisual Studio Codeが立ち上がってきます。
クリップボードも有効になっているので、windowsアプリが開いているような状態で扱う事が出来ます。日本語入力設定
日本語入力の切り替えキー設定は以下コマンドで実行します。
fcitx-config-gtk3
Mozc自体の設定ダイアログは、以下のコマンドで開けます。
$ /usr/lib/mozc/mozc_tool --mode=config_dialog
[参考]
WSL(Ubuntu 18.04)上でVS Codeを動かす
その他
chromeの起動
dockerの中でchromeを起動する場合、sandbox を切っておかないと起動する事が出来ません。
このため、以下のようなエイリアスを張っています。
ターミナルより「chrome&」と入力する事でchromeが起動可能となります。alias chrome="google-chrome-stable --no-sandbox --disable-dev-shm-usage"
インストール済みコマンド一覧
コマンド プログラム chrome google chreom code Visual Studio Code /usr/lib/mozc/mozc_tool --mode=config_dialog Mozcの設定 参考
DockerでポータブルなLinux開発環境(GUI付き)を構築する
↑
基本的にはこの記事をベースにさせて頂きました。install nvm in docker
↑
dockerの中でnvmしようとしたらはまりました...。【Linux小技】 scp(ssh)での暗号化方式の違いによる転送速度ベンチマーク
↑
X転送が遅いのでsshの暗号を切り替えました。
その参考です。WSL(Ubuntu 18.04)上でVS Codeを動かす
18.04の環境に更新する時に参考にさせて頂きました。
- 投稿日:2019-12-30T14:36:56+09:00
DockerfileのRUNやCMDをBashのログインシェルで実行させる
または、sdkman, rbenv, nvmなどのパッケージマネージャをDockerfileやコンテナで動かす方法について。
TL;DR
Dockerfileの
RUN
がbashかつログインシェルで動いてほしいときDockerfileSHELL ["/bin/bash", "-l", "-c"]Dockerfileの
CMD
や、docker run
に渡したコマンドがbashのログインシェルで動いてほしいときDockerfileRUN echo '#!/bin/bash\nexec /bin/bash -l -c "$*"' > /entrypoint.sh && \ chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]経緯
諸事情でJava, Gradle, Ruby, Node.jsをそれぞれ指定されたバージョンでインストール済みのコンテナイメージを作る必要があった。
apt-getなどOS標準のパッケージマネージャで過去のバージョンを指定してインストールしたり、個別にインストールするのが面倒に感じたため、sdkman, rbenv, nvmといったバージョンマネージャをDockerfile内でインストールして使うことにした(いろいろあって結局使うのをやめたが……)。しかしこれらのツールは、Dockerfile内ではうまく動作しなかった。
なぜならsdkmanなどのバージョンマネージャは
- bashを前提としているものがある(関数やsourceコマンドなど)
.bashrc
で初期化スクリプト(PATHの設定など)が実行されるつまり、動作にはbashかつログインシェルで実行される必要がある。一方、Dockerfileの
RUN
命令はデフォルトで
/bin/sh -c
の引数として実行される- bashでもログインシェルでもないため
.bash_profile
や.bashrc
が実行されない解決策
SHELL
命令を使うとDockerfile内のRUN
がどのシェル+引数によって実行されるかを指定できる。SHELL ["/bin/bash", "-l", "-c"]また、
ENTRYPOINT
命令でCMD
やdocker run
に渡したコマンドを実行するプロセスを指定できる。これは以下のシェルスクリプトを実行させると大抵の場合うまくいくという結論に達した。/entrypoint.sh#!/bin/bash exec /bin/bash -l -c "$*"ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT
の指定について上の
entrypoint.sh
はずいぶん回りくどく感じると思うので、いくつか他にも試して問題があったケースを挙げておく。
SHELL
と同じ指定をした場合ENTRYPOINT ["/bin/bash", "-l", "-c"]
-c
オプションが引数を1つしか受け取らないため、CMD
やdocker run
でコマンドをまとめて1つの文字列として渡す必要があり、かなり面倒。shebangでログインシェルを指定して
exec
だけで実行させた場合/enrtypoint.sh#!/bin/bash -l exec $*
exec
コマンドの第1引数には実行ファイルを指定する必要があるため、関数やbash組み込みのコマンドが実行できない。
sdk
,rbenv
,nvm
はそれぞれ関数として実装されているため実行できなかった。
- 投稿日:2019-12-30T09:49:04+09:00
docker-lambda + minioで環境構築
AWS S3互換であるminioと、lamda function開発用のdocker imageであるdocker-lambdaを使って、ローカルで開発環境を作ろうというお話です。
Minio
MinioはAWS S3互換のObject Strageで、ローカルにS3環境を作ることができます。
公式ドキュメントも用意されており、Dockerがあれば手軽にはじめられます。minio server
サーバーの立ち上げは以下のコマンド。
$ docker run --name minio -p 9000:9000 -it minio/minio server /data上記コマンドを打った後、おそらく以下のようなものが表示される。
mc
コマンドについては次に説明する。Endpoint: http://172.17.0.2:9000 http://127.0.0.1:9000 AccessKey: minioadmin SecretKey: minioadmin Browser Access: http://172.17.0.2:9000 http://127.0.0.1:9000 Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide $ mc config host add minio http://172.17.0.2:9000 minioadmin minioadminminio client
このminioにはコマンドも用意されている。これによってローカルで立てたminioサーバーに対してコマンドから操作を行うことができる。
mcを起動後、さきほどminio serverを立ち上げたときに表示されていたmc
ではじまるコマンドをコピペする。
これでminio serverとの接続が完了。この先はコマンドでminio serverを操作することが可能となる。$ docker pull minio/mc $ docker run --name mc -it --entrypoint=/bin/sh minio/mc # mc config host add minio http://172.17.0.2:9000 minioadmin minioadmindocker-lambda
そしてlambda fuction開発用のdocker imageであるdocker-lambda。
Amazon Lambda Functionの中身はAmazon linuxらしく(知らなかった)、それをDocker内で環境構築し、必要なパッケージをインストールしてzipで固めて〜...を簡単に行えるようにしたもの。コマンドの基本形は以下
$ docker run --rm -v <code_dir>:/var/task lambci/lambda:<runtime> <filename>.<funcname>以下のファイルを適当なディレクトリで作成。
function.pydef my_handler(event, context): message = 'Hello {} {}!'.format(event['first_name'], event['last_name']) return { 'message' : message }上記ファイルがあるディレクトリで以下のコマンドを叩くと、それでテストができる
$ docker run --rm -v "$PWD":/var/task lambci/lambda:python3.7 function.my_handler \ '{"first_name": "Kenji", "last_name": "Yamada"}'上記コマンドを叩いた場合はイベントが起こった前提でのテストができ、即終了となるが、
DOCKER_LAMBDA_STAY_OPEN=1
というオプションをつけることでAPIサーバーとしてdocker-lambdaを起動することができる。$ docker run --rm \ -e DOCKER_LAMBDA_STAY_OPEN=1 \ -p 9001:9001 \ -v "$PWD":/var/task \ lambci/lambda:python3.7 \ function.my_handler以下のコマンドでイベントを投げることができる。
$ curl -d '{"first_name": "Kenji", "last_name": "Yamada"}' http://localhost:9001/2015-03-31/functions/myfunction/invocations本題
ここまでが今回使うツールの説明である。
そして上記で説明したものはだいたい検索すれば出てくる。
今回やりたいことは以下の2つ
- Minioにはwebhookの設定があるらしい
- Minioにファイルをおいたタイミングでdocker-lambdaを動かしたい
ネットワークの設定
複数のコンテナを立ち上げて通信するため、まずはネットワークの設定を行う
$ docker network create minio-lambda-netlambdaをAPIサーバーとして立ち上げ
まず、以下のようなlambda functionを作成する。
内容はシンプルに、S3にファイルをおいたタイミングでS3の情報を表示するだけ。
今回はS3の代わりにMinioを使っているので、endpointにminioのurlをしていする。function.pyfrom __future__ import print_function import os import json import urllib import boto3 print('Loading function') print('AWS_ACCESS_KEY_ID: ', os.environ.get('AWS_ACCESS_KEY_ID')) print('AWS_SECRET_ACCESS_KEY: ', os.environ.get('AWS_SECRET_ACCESS_KEY')) s3_endpoint_url = 'http://minio:9000' #http://boto3.readthedocs.io/en/latest/reference/services/s3.html#client s3 = boto3.client('s3', endpoint_url=s3_endpoint_url) def lambda_handler(event, context): print(event) bucket_name = event['Records'][0]['s3']['bucket']['name'] print('==== bucket information =====') print(bucket_name) print('=============================') #https://github.com/bloomberg/chef-bcs/blob/master/cookbooks/chef-bcs/files/default/s3-example-boto3.py print('==== your bucket list ====') buckets = s3.list_buckets() for bucket in buckets['Buckets']: print(bucket.get('Name')) print('==== file list in bucket ====') # https://github.com/boto/boto3/issues/134 AWS_S3_BUCKET_NAME = 'test' s3_resource = boto3.resource('s3', endpoint_url=s3_endpoint_url) bucket = s3_resource.Bucket(AWS_S3_BUCKET_NAME) result = bucket.meta.client.list_objects(Bucket=bucket.name, Delimiter='/') for o in result.get('Contents'): print(o.get('Key')) print('==== uploaded file ====') for rec in event['Records']: print(rec['s3']['object']['key']) print('=============================') print("Received event: " + json.dumps(event, indent=2))サーバーの起動は以下のコマンド。
$ docker run --rm --name d-lambda -p 9001:9001 --net=minio-lambda-net -e DOCKER_LAMBDA_STAY_OPEN=1 -v "$PWD":/var/task lambci/lambda:python3.7 function.lambda_handlerMinio serverのwebhookの設定
Minio serverにはBucket Notificationという機能があり、方法は色々あるがwebhookを使ってMinioでのイベントを通知してみようというお話。
注意すべき点はendpointの設定。さっきd-lambdaという名前でサーバーを起動しているので、ホスト名をd-lambdaにする。
# mc admin config get myminio/ notify_webhook # mc admin config set myminio notify_webhook:1 queue_limit="0" endpoint="http://d-lambda:9001/2015-03-31/functions/myfunction/invocations" queue_dir="" ここで一度サーバーを再起動するように指示されるので、それに従う。 # mc admin service restart myminio # mc mb myminio/test # mc event add myminio/test arn:minio:sqs::1:webhook --event put --suffix .mp4 # mc event list myminio/test上記の設定を行うことで、testという名前のbucketに*.mp4というファイルが送られたら、webhookの通知を行うことができる。
以上で設定は完了となる。
http://localhost:9000 にアクセスするとMinioのWebUIが表示されるので、そこからファイルをアップロードしてみましょう。
lambdaを立てたコンソールで結果が見えるはずです。参考