いがにんのぼやき

WEBエンジニアのブログ。IT、WEB、バンド、アニメ。

Swagger EditorとSwagger UIをDockerで動かす

Swagger Editor

docker pull swaggerapi/swagger-editor
docker run -d -p 81:8080 --name swe swaggerapi/swagger-editor

一部generator.swagger.ioから外部リソースを取得してるみたい。
初期表示のAPI仕様は外部から取得したファイルを表示しているよう。

github.com

今のSwagger Editorはここら辺を変更できなくて、後述のSwagger UIだと変更できるようだ。

Swagger UI

docker pull swaggerapi/swagger-ui
docker run -d -p 82:8080 --name swu swaggerapi/swagger-ui

中身を見ているとDocker起動時に環境変数を設定することで一部パラメータを変更できるようになっている。
例えば下記のようにAPI_URLを設定することで表示に使用するJSONを変更したりできる。

docker run -d -p 82:8080 --name swu -e API_URL=http://generator.swagger.io/api/swagger.json swaggerapi/swagger-ui

2018/02/21現在での最新コミットではポートやOAUTH関係の環境変数が設定できるようになっている。

Dockerfile

Docker使用時に走るdocker-run.shというファイルで環境変数を使った設定を行っている。 この環境変数に関するドキュメントがどこかにあれば教えてほしい。

docker-run.sh

こんな風にSWAGGER_JSONという環境変数にコンテナ内で存在するファイル名を指定してあげるとそれをSwager UIに表示することができる。

docker run -d -p 82:8080 --name swu -e "SWAGGER_JSON=/test.json" -v d:/Docker/swagger/test.json:/test.json swaggerapi/swagger-ui

docker-compose

docker-composeだとこんな感じ。

  swagger-editor:
    image: swaggerapi/swagger-editor
    container_name: "xxx-swagger-editor"
    ports:
      - "8081:8080"

  swagger-ui:
    image: swaggerapi/swagger-ui
    container_name: "xxx-swagger-ui"
    ports:
      - "8082:8080"
    volumes:
      - ./swagger/test.json:/test.json
    environment:
      SWAGGER_JSON: /test.json

ElectronをWindowsのBash(WSL)で試してみて成功しなかった

毎度毎度の失敗談。
Electronを試してみたいと思って、可能ならばWindowのBashとして機能するWindows Subsystem for Linux上で実行したいと思って試してみた。
結局動かなかったけど。
詳しい方がいたら情報求む。
一応記録として残しておく。

まずは公式サイトのクイックスタートを試してみる

そもそもNode.jsが入っていなかったのでインストール

$ sudo apt-get install -y nodejs npm

Node.jsのバージョン管理ツールであるnを使ってみます。

$ sudo npm install -g n

実行する前にBashを一度閉じて再起動しておきます。
そうしないとエラーが発生しました。

$ sudo n stable

     install : node-v9.4.0
       mkdir : /usr/local/n/versions/node/9.4.0
       fetch : https://nodejs.org/dist/v9.4.0/node-v9.4.0-linux-x64.tar.gz
######################################################################## 100.0%
   installed : v9.4.0
$ node -v
v9.4.0
$ which node
/usr/local/bin/node
$ npm -v
5.6.0
$ which npm
/usr/local/bin/npm
$

apt-getでインストールしたNode.jsとnpmは削除しておく。

$ sudo apt-get purge nodejs npm

Electronのサンプルアプリをcloneして実行してみる。

$  git clone https://github.com/electron/electron-quick-start
$ npm install && npm start

> electron@1.7.12 postinstall /mnt/d/Programming/JavaScript/electron-quick-start/node_modules/electron
> node install.js

npm notice created a lockfile as package-lock.json. You should commit this file.
added 152 packages in 43.837s

> electron-quick-start@1.0.0 start /mnt/d/Programming/JavaScript/electron-quick-start
> electron .

/mnt/d/Programming/JavaScript/electron-quick-start/node_modules/electron/dist/electron: error while loading shared libraries: libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directory
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! electron-quick-start@1.0.0 start: `electron .`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the electron-quick-start@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T14_29_04_074Z-debug.log

エラーが発生して実行が出来なかった。
ここからは延々と依存関係にあるパッケージをインストールしていくだけで、結局成功していないので注意

libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directoryとあるのでインストールしてみるとエラーが変わった。

$ sudo apt-get install libgtkextra-dev

こんな感じで一つ一つ毎回エラーが変わって依存パッケージがないと出るのでそれが消えるまでインストールしていった。

存在しないと言われるファイル インストールしたパッケージ名
libX11-xcb.so.1 libx11-xcb-dev
libXtst.so.6 libxtst6
libXss.so.1 libxss1
libgconf-2.so.4 libgconf-2-4
libnss3.so libnss3-dev
libasound.so.2 libasound2

一部参考

github.com

上記をインストールしていったらエラーが出るがエラー詳細が出なくなり困った。

$ npm start

> electron-quick-start@1.0.0 start /mnt/d/Programming/JavaScript/electron-quick-start
> electron .

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! electron-quick-start@1.0.0 start: `electron .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the electron-quick-start@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T14_59_57_523Z-debug.log

もうお手上げ状態。
下記のような記事を挙げている人がいて、上記のエラーと同等かは分からないが動作するようになっているらしい。

grugrut.hatenablog.jp

一度グローバルにElectronを入れてみる

一度グローバルにElectronコマンドをインストールしてそちらを叩けるか試してみた。

sudo npm install -g electron
$ sudo npm install -g electron
[sudo] password for iganin:
/usr/local/bin/electron -> /usr/local/lib/node_modules/electron/cli.js

> electron@1.8.2 postinstall /usr/local/lib/node_modules/electron
> node install.js

/usr/local/lib/node_modules/electron/install.js:47
  throw err
  ^

Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/electron/.electron'
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! electron@1.8.2 postinstall: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the electron@1.8.2 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T15_29_31_278Z-debug.log

エラーが発生した

sudo npm install -g electron --unsafe-perm=true --allow-root

これでインストールは出来た。
けどコマンドを実行しても何も表示されないという状況で謎。

結局

Windowsは難しい。
今度はWindows自体(Powershellとか)で実行できないか試してみようと思う。
WSLの問題なのかElectronの問題なのか・・・。
Windows関係、毎回失敗を繰り返しすぎて心が強くなっていくのを感じる。

Laravelのユーザー関係のルート定義がどこにあるか

Laravelにはユーザーを作成、認証する機能がある。
Laravel 5.4ではphp artisan make:authコマンドを打つと特定のコントローラーとビューに加えて、routes/web.phpAuth::routes();という記述が追加される。
このroutesメソッドでユーザー関係のルーティングが定義されるようだが、どこにあるかよく分からなかったので調べて見た。

まずはルート定義を確認

$ php artisan route:list
+--------+-----------+------------------------------+----------------------+------------------------------------------------------------------------+--------------+
| Domain | Method    | URI                          | Name                 | Action                                                                 | Middleware   |
+--------+-----------+------------------------------+----------------------+------------------------------------------------------------------------+--------------+
|        | GET|HEAD  | home                         | home                 | App\Http\Controllers\HomeController@index                              | web,auth     |
|        | GET|HEAD  | login                        | login                | App\Http\Controllers\Auth\LoginController@showLoginForm                | web,guest    |
|        | POST      | login                        |                      | App\Http\Controllers\Auth\LoginController@login                        | web,guest    |
|        | POST      | logout                       | logout               | App\Http\Controllers\Auth\LoginController@logout                       | web          |
|        | POST      | password/email               | password.email       | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail  | web,guest    |
|        | GET|HEAD  | password/reset               | password.request     | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest    |
|        | POST      | password/reset               |                      | App\Http\Controllers\Auth\ResetPasswordController@reset                | web,guest    |
|        | GET|HEAD  | password/reset/{token}       | password.reset       | App\Http\Controllers\Auth\ResetPasswordController@showResetForm        | web,guest    |
|        | GET|HEAD  | register                     | register             | App\Http\Controllers\Auth\RegisterController@showRegistrationForm      | web,guest    |
|        | POST      | register                     |                      | App\Http\Controllers\Auth\RegisterController@register                  | web,guest    |

こんな感じでユーザーに関するルーティングが追加されている。

Auth::routes()

Illuminate\Support\Facade\Authクラスにその定義が存在する。

<?php
/**
 * Register the typical authentication routes for an application.
 *
 * @return void
 */
public static function routes()
{
    static::$app->make('router')->auth();
}

$appはIlluminate\Foundation\Applicationクラスである。
$app->make('router')はIlluminate\Routin\Routerクラスを返し、そのRouterクラスのauthメソッドに、今回のユーザー関係の定義が書かれている。

<?php
/**
 * Register the typical authentication routes for an application.
 *
 * @return void
 */
public function auth()
{
    // Authentication Routes...
    $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
    $this->post('login', 'Auth\LoginController@login');
    $this->post('logout', 'Auth\LoginController@logout')->name('logout');

    // Registration Routes...
    $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
    $this->post('register', 'Auth\RegisterController@register');

    // Password Reset Routes...
    $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
    $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
    $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
    $this->post('password/reset', 'Auth\ResetPasswordController@reset');
}

これがAuth::routes()の正体である。

余談

ちなみにIlluminate\Routing\RoutingServiceProviderに今回の$app->make('router')で生成されるインスタンスの定義はIlluminate\Routing\RoutingServiceProviderに存在している。
DIコンテナの定義だ。

<?php
/**
 * Register the router instance.
 *
 * @return void
 */
protected function registerRouter()
{
    $this->app->singleton('router', function ($app) {
        return new Router($app['events'], $app);
    });
}

元々のサービスプロバイダーの登録もconfig/app.phpに定義してあるわけではなく、先ほどのApplicationクラスで行なっているようだ。

<?php
/**
 * Register all of the base service providers.
 *
 * @return void
 */
protected function registerBaseServiceProviders()
{
    $this->register(new EventServiceProvider($this));

    $this->register(new LogServiceProvider($this));

    $this->register(new RoutingServiceProvider($this));
}

このコアの実装は後々追って行きたい。

漠然とした自社サービス開発に携わりたいという思い

前職の退職理由のひとつに受託開発ではなく、自社サービスに携わりたいというものがある。

僕自身は何故そう思ったのだろうか。
それを自問自答したい。

そもそもの始まり

何となく感じたのは入社して2年目が始まったあたりだろうか。
とあるLPページを作成した。そのサイトのコンバージョンがそのまま会社の売り上げに繋がるというものだ。
外部の業者の用意した商材をLPでアピールし、最終的に発注となればうちにマージンが入るというもの。
コンバージョンの具体的な数字は知らされなかったが、発注お問い合わせの情報は僕にも届くようになっていた。
LPをリリースして数日後初めてのお問い合わせが届いた。
その時、とても嬉しかったのである。
小さい、それもまだ発注にも繋がっていないお問い合わせなのだが、自分の作成したLPが人の求められるものとして認識されたからだろうか、とても嬉しくて社内でプロジェクトメンバーにウキウキしながら知らせたのを覚えている。

その時、感じたのである。
僕はこんな風にサービスを届けたいんだなと。
前々から自社サービスをやりたいと思っていたが、確実に志向が変わったのを確信した出来事だった。

誇れるもの

勉強会や交流会に参加すると、楽しそうに自社のサービスを語る人たちがいる。
このサイトのこの箇所はこんな議論があって、結果的にこうなって、その試行錯誤がたまらなく楽しそうに語るのである。

受託開発ではおおっぴらに言えないようなこともある。(もちろん、自社サービスでも言えないことなんてたくさんあるだろうけど)
試行錯誤した結果、顧客に納得してもらったとき、上記のように話せる場面は少ない。

自社サービスと受託開発で大きく違うのはエンジニアの作ったものを納得させるビジネスサイドが、身内(社内)か外(顧客)かである。
僕は身内を説得し、最終的にエンドユーザーに価値を届けるということをしたい。
受託では顧客を納得させれば、そのシステムを最終的に使うエンドユーザーの体験に関与することはない。
それをとても歯痒く感じていた。

改善

そして、一番歯がゆいのがリリースされたものを改善することが許されないことにある。
後々考えればパフォーマンス的によくないコードだったり、それがエンドユーザーに影響を与えていようと、客の発注が来なければ動くことはできない。
受託開発において勝手に動くことはただのコスト、無償ボランティアとなるからである。
これはビジネス的には当たり前のことで、そのパフォーマンスのせいで顧客のCVRが落ちようとも自社には一切影響はない。
顧客がそこまで分析できて問題点を指摘できるレベルであれば別だが、そんな企業は存在しないし、そのレベルまで行けば内製化を進められるであろう。

この改善ができないというのはエンジニアとしてはとても危険な状況だと思っていて、これによってあのコードは良かった、悪かったという議論も計測もできないのである。
これでは成長を止めてしまうだろう。

でもどこかで能力を売り出していかなければいけない

それはわかっているんだ。
自分の学んだものを切り出していくような仕事をしたほうがお金を稼ぎやすい。
挑戦にはコストがかかる。
いつかはそうやって切り出していって稼いでいく時が来るだろう。
だけど今はその時じゃないと思っている。
20代という社会人としては最も若い部類に入る歳で、そのような働き方をしていくと歳をとったときに苦労するだろうというのが僕の見解だ。
悲しいことにこの若さで年々学習能力に衰えを感じていて、実際に歳をとったときに学習していける自信がない。
ならば20代で技術を売りに出すのではなく学べるような環境に身を置くべきと思っている。
この学習・挑戦と、能力の売り出しのバランスはうまく取っていきたい。

だいたい新卒エンジニア向け技術交流会 vol.13に参加、発表してきた

dark.connpass.com

だいたい新卒エンジニア向け技術交流会 vol.13で 発表してきた。
資料はこちら。

qiita.com

完全にネタ枠のつもりで行ったので技術的なことは一切ない。
楽しんでもらえたようなので良かった。

前回のLT会のときも発表させていただいて、その時はCMSエンジニアについて話した。
前回、今回と前職のお話をしていて、ある程度前職のお話を話し切った感はある。(今は勉強期間&転職活動で無職です。)

LTや記事に書き起こすことによって、その出来事に区切りをつけることができると思っていて、今回はこの場を借りて発表させていただいた。
これで前職に関して一つの区切りを付けられた。
明日からまた次の一歩を歩んでいけるような気がしている。

がんばるぞ!!!

以下は雑な他の方の発表のメモ

dev.toの速さについての小話@hi-sa

  • 今話題のdev.to
  • fastlyやマウスオーバー時の先読みHTMLは強い

最新技術のキャッチアップ@speech

  • TECH FEED知ってはいたが使ってみようかなって思った
  • 新卒にしか見えない資料辛い

何も準備せずにノリで上海に行ったら大変だった話@bird_nitryn

Docker使ってますか?@tunamaro

  • 開発環境DBの切り替えと便利そう

おいしいカクテルの作り方@14万(sota1235)

  • 14万!!!!!!!!
  • ポジティブは大切

休職したときに受ける損害とその軽減方法@equal_001

  • 診断書が5000円とかするとか、高いのね
  • 企業によっては出社8割満たないと有給が貰えない
  • 心が弱っているときに交渉事をしなければいけないのは大変だと思った

人材業界中の人が語る若手エンジニアの転職活動@momotomo

  • エージェントさんは面倒な交渉事、日程調整をやってくれたり有難い
  • 内定承諾を待つ期間が短いので面接が集中するので注意

P.S

無事14万を渡すことが出来てよかったです。

PhpStorm + Docker for Windowsを試す

Docker for Windowsの設定を開き、Generalタブを選択する。
Expose daemon on tcp://localhost:2375 without TLS にチェックをつける。

f:id:igatea:20171211185955p:plain

PhpStormのDockerの設定を行う。
設定を開きDockerと検索し、Build, Execution, DeploymentのDockerを選択する。
プラスボタンを押し、TCP socketを選択するとウィンドウ配下に接続可能か検証結果が表示される。

f:id:igatea:20171211190108p:plain

Connection succesfulと表示されれば成功。

再度、設定を開きPHPと検索。
Languages & Frameworksの中のPHPを選択し、CLI Interpreterの...をクリック。

f:id:igatea:20171211190558p:plain

Docker(またはDocker Compose)が選択されていることを確認し、Serverを先ほど作成したDockerの設定を選択する。

PHP veresin: Not installedと表示される。

f:id:igatea:20171211190946p:plain

おそらくDockerをビルドしていないからだと予想。
該当ディレクトリでdocker-compose build

それでもエラーが出ているのでdocker-compose up -dで立ち上げてみる。

やはりだめ。

com.github.dockerjava.api.exception.BadRequestExceptions: {"message":"invalid environment variable: =::=::\\"}

f:id:igatea:20171211204031p:plain

MobyLinuxVMではなく、別にHyper-V上にDocker Machineを立ててやってみようとしたけど駄目だった。

Docker Compose経由を諦めて、Docker単体で動作させてみた。

Testing started at 2:43 ...
docker://laravelsampleblog_php:latest/php vendor/phpunit/phpunit/phpunit --configuration /src/phpunit.xml --teamcity
Could not open input file: vendor/phpunit/phpunit/phpunit

Process finished with exit code 1

パスが解決できてないっぽい?
どうもここから進まない。

Windowsにすることによって、Ubuntuのときよりも構築障壁が高くなりすぎている。
.Net系以外は仮想環境でUbuntuでも立てて、そこで開発するようにするか検討しようと思う。

2017/12/18追記
f:id:igatea:20171218172449p:plain Include parent environment variablesのチェックを外したら正常に動作しました!!

f:id:igatea:20171218172937p:plain

この一番上の変数がよくないようだ。
だけどこれがどこで定義されているものなのかがわからない。
コマンドプロンプトPowerShellか、変数が定義されているのかと思って確認してみたがそれらしいものは無し。
とりあえず動かすことができてよかったが、もやもやが残っている。