20200224のdockerに関する記事は22件です。

dockerネットワークのipv6対応方法と通信経路の整理

概要

squidでActiveDirectory連携とSSLインターセプトするProxyをdockerで手軽につくる で、squid4.4の構築時に
squidがIPv6で自分自身にアクセスするため、dockerもIPv6を有効化する必要がありました。
手順と通信経路について整理します。

dockerエンジン・デーモンのIPv6化

以下のファイルを作成し、デーモンを再起動します。
IPv6の表記はドキュメント用なので、適宜修正ください。

/etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

すでに daemon.json がある場合には、上記を追記してください。

systemctl restart docker

止めたくないから reload してみたけど、反映されなかったので、 restart しました。

参考:https://docs.oracle.com/cd/E77565_01/E87205/html/docker_install_upgrade_ipv6.html

Dockerネットワークとコンテナ

IPv6を有効化したネットワークを作成し、そこに生成したコンテナを参加させる。

# docker network create --ipv6  --driver=bridge  --subnet=fd5a:ceb9:ed8d:1::/64 br_ipv6_nw \
   -o com.docker.network.bridge.name="br_ipv6_nw"
# docker run --network br_ipv6_nw --name cnt01 -it -d centos:centos8 /bin/bash

Dockerネットワークの状態

# docker network inspect br_ipv6_nw
[
    {
        "Name": "br_ipv6_nw",
        "Id": "ae1e90ac38bbdd208394922263053e8cfac4d31d6d6bbfecf50c345f18606e30",
        "Created": "2020-02-24T18:36:33.239261559+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": true,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.26.0.0/16",
                    "Gateway": "172.26.0.1"
                },
                {
                    "Subnet": "fd5a:ceb9:ed8d:1::/64"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "286e2d07ab7a0d04f061ffbe4451f2a5d0a6553ad4cf6063ab21f7cdb4f40441": {
                "Name": "cnt01",
                "EndpointID": "d057150483d194c0e95eca386189482b431cff3b351411b01cb0394b92dd1852",
                "MacAddress": "02:42:ac:1a:00:02",
                "IPv4Address": "172.26.0.2/16",
                "IPv6Address": "fd5a:ceb9:ed8d:1::2/64"
            }
        },
        "Options": {
            "com.docker.network.bridge.name": "br_ipv6_nw"
        },
        "Labels": {}
    }
]

DockerホストとDockerコンテナのインターフェース

Dockerホスト

インターフェース
ホストのインターフェースIDはsubnetの最若番になる。
と、リンクローカルも最若番のfe80::1になる。

# ip add
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:62:2e:fa brd ff:ff:ff:ff:ff:ff
    inet 10.254.10.252/24 brd 10.254.10.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet6 fd5a:ceb9:ed8d:fe0a:ed57:61d8:20eb:aba5/64 scope global dynamic noprefixroute
       valid_lft 2591966sec preferred_lft 604766sec
    inet6 fe80::f7f9:b2ce:3e89:7281/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
75: br_ipv6_nw: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:c1:de:82:5c brd ff:ff:ff:ff:ff:ff
    inet 172.26.0.1/16 brd 172.26.255.255 scope global br_ipv6_nw
       valid_lft forever preferred_lft forever
    inet6 fd5a:ceb9:ed8d:1::1/64 scope global tentative
       valid_lft forever preferred_lft forever
    inet6 fe80::1/64 scope link tentative
       valid_lft forever preferred_lft forever

ルーティング(関係ないdocker0は除外しています)
デフォルトはens192の対向先

# ip -6 route | grep -v docker0
::1 dev lo proto kernel metric 256 pref medium
fd5a:ceb9:ed8d:1::/64 dev br_ipv6_nw proto kernel metric 256 pref medium
fd5a:ceb9:ed8d:fe0a::/64 dev ens192 proto ra metric 100 pref medium
fe80::/64 dev ens192 proto kernel metric 100 pref medium
fe80::/64 dev br_ipv6_nw proto kernel metric 256 pref medium
fe80::/64 dev veth671b926 proto kernel metric 256 pref medium
default via fe80::1 dev ens192 proto ra metric 100 pref medium

Dockerコンテナ

インターフェース
ホストのインターフェースIDはDockerホストから昇順での割り当ての模様。
と、リンクローカルはMACアドレスからの自動採番かな。

# docker exec -it cnt01 bash
[root@45b84c2182a5 /]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
82: eth0@if83: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:1a:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.26.0.2/16 brd 172.26.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fd5a:ceb9:ed8d:1::2/64 scope global nodad
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe1a:2/64 scope link
       valid_lft forever preferred_lft forever

ルーティング
デフォルトはULAのDockerホストになるみたい。

# ip -6 route
fd5a:ceb9:ed8d:1::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fd5a:ceb9:ed8d:1::1 dev eth0 metric 1024 pref medium

疎通確認

ホスト → コンテナ の通信確認

# ping6 -c 1 fd5a:ceb9:ed8d:1::2 | grep icmp_seq
64 bytes from fd5a:ceb9:ed8d:1::2: icmp_seq=1 ttl=64 time=0.297 ms
# ping6 -c 1 fe80::1%br_ipv6_nw | grep icmp_seq
64 bytes from fe80::1%br_ipv6_nw: icmp_seq=1 ttl=64 time=0.195 ms

コンテナ → ホスト の通信確認

# ping6 -c 1 fd5a:ceb9:ed8d:1::1 | grep icmp_seq
64 bytes from fd5a:ceb9:ed8d:1::1: icmp_seq=1 ttl=64 time=0.114 ms
# ping6 -c 1 fe80::1 | grep icmp_seq
64 bytes from fe80::1%eth0: icmp_seq=1 ttl=64 time=0.129 ms

コンテナ → ホスト → 外部 の通信確認

# ping6 -c 1 dns.google | grep icmp_seq
64 bytes from dns.google (2001:4860:4860::8844): icmp_seq=1 ttl=52 time=6.74 ms

通信経路

概略

dns.google に ping6 したとき、以下のように通信を行います。

HOSTではIPマスカレードして、srcアドレスをHOSTのアドレスに置き換えます。
GATEWAYでは、fd5a:ceb9:ed8d:fe0a::/64 を ROUTINGPREFIX:ff66/64 にNPTv6 しています。

Screenshot from Gyazo

HOSTの設定と動作

DockerホストのIPマスカレードは firewall-cmd --masquerade --zone=public --permanent により以下のルールが追加されています。

# nft list chain ip6 firewalld nat_POST_public_allow
table ip6 firewalld {
        chain nat_POST_public_allow {
                oifname != "lo" masquerade
        }
}

これによりコンテナからのパケットはホストでSNATされます。
conntrackで確認すると、以下のようになっています。

# conntrack -E -p icmpv6
    [NEW] icmpv6   58 30 src=fd5a:ceb9:ed8d:1::2 dst=2001:4860:4860::8888 type=128 code=0 id=38 [UNREPLIED] src=2001:4860:4860::8888 dst=fd5a:ceb9:ed8d:fe0a:ed57:61d8:20eb:aba5 type=129 code=0 id=38
 [UPDATE] icmpv6   58 30 src=fd5a:ceb9:ed8d:1::2 dst=2001:4860:4860::8888 type=128 code=0 id=38 src=2001:4860:4860::8888 dst=fd5a:ceb9:ed8d:fe0a:ed57:61d8:20eb:aba5 type=129 code=0 id=38

ROUTERの設定と動作

ROUTERのルーティングは以下のように設定されています。
(なんでfe80::1にしなかったんだっけ。。。)

Rdc01#sh run | in ::/0
ipv6 route ::/0 Vlan252 FD5A:CEB9:ED8D:FEFC::1

GATEWAYの設定と動作

GATEWAYのインターフェースは以下のように設定されています。
(いまだにCLI使いこなせない。。。)

admin@FWdc01> show interface all
(~省略~)
ethernet1/1.999     271   1    zUntrust         vr:default               999    192.168.1.250/24
                                                                                fe80::b60c:25ff:fe0f:df10/64
                                                                                ROUTINGPREFIX:ffff:192:168:1:250/64
                                                                                fe80::192:168:1:250/128
(~省略~)
ethernet1/2.252     260   1    zTrust           vr:default               252    10.254.252.1/24
                                                                                fe80::b60c:25ff:fe0f:df11/64
                                                                                fd5a:ceb9:ed8d:fefc::1/64
                                                                                fe80::1/128
(~省略~)

GATEWAYのNPTv6は以下のように設定されています。
本当は Prefix64bit ごとに NPTv6のトランスレータを準備しないといけないのですが、手抜きで2セグをまとめています。

"nat66_NPTv6_to_internet; index: 1" {
        nat-type nptv6;
        from zTrust;
        source [ fd5a:ceb9:ed8d:fe0a:0:0:0:0/64  fd5a:ceb9:ed8d:fefc:0:0:0:0/64  ];
        to zUntrust;
        to-interface ethernet1/1.999 ;
        destination any;
        service 0:any/any/any;
        translate-to "src: ROUTINGPREFIX:ff66:0:0:0:0/64 (static-ip) (pool idx: 0)";
        terminal no;
}

これによりパケットはGATEWAYでSNATされます。
NAT後のトラフィックログは、以下のようになっています。
(CLIの確認方法がわからなかった。。。)

Screenshot from Gyazo

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

一晩でReact×Laravel(API)×Dockerを利用したWebサービスを作ったTDD(徹夜駆動開発)のお話

はじめに

初めまして、大阪でWebエンジニアをしているかっぽと申します。
今回、主催者の並里氏のお誘いもあり大阪で行われた一泊二日のエンジニア合宿に参加してきたのですが
思っていた以上に刺激的で有意義な時間を過ごせましたので記事にしようと思い書いている次第です。
こちらの記事は合宿についての自分チーム主体の偏見の塊のような個人的共有レポートです。

第1回大阪エンジニア開発合宿(OsakaDevelopmentCamp)とは

2020/02/22(土) 〜 2020/02/23(日) に大阪の難波周辺で行われたエンジニアの開発合宿
Laravelのもくもく会や勉強会、ハンズオンなど多くのエンジニアのイベントを企画しているナミザト氏の今度開発合宿やってみたいな〜というぽっとでのツイートをきっかけに賛同したフットワーク軽めのエンジニア9人が集まり、3人1チームとなって前日から次の日の朝まで眠らずにひとつWebサービスを開発するというエンジニアにとって夢のような合宿です

前置き

今回の開発合宿の参加者

チームサイトウ

チームアマゾネス

チームじゃけぇ

合宿日時

2020/02/22(土) 16:00 〜 2020/02/23(日) 10:00

当日の予定

当日はチームで一つの成果物(web/アプリ問わない)を23日の7時までに作成して、
23日の8時にはみんなの前でそれぞれ成果物を発表する

合宿のルール

  • 技術選定はチームで話し合い決定する
  • 成果物はチームで話し合い決定する
  • 開発終了後の成果物の所有等はチームで話し合い決定する(自由)

今回の合宿、開始日までに環境構築や事前準備はOKですが、実装は開始日の16:00からしか行ってはいけないという暗黙のルールがありました。
しかし、なんと3チーム中2チームが16:00以前から実装を進めていたとの情報が!!(ずるい)

16:30~ 合宿開始

そんなこんなで始まった開発合宿ですが、さすが有名なエンジニアさんが多く集まっているだけあって、始まったとたんからバリバリと実装を開始しました。(私のチーム以外は。)
IMG_0706.JPG

ふんわりとしか役割を決めていなかった私のチーム、チームじゃけぇはその姿を見て呆然とし、

「え、あ、フロントする?サーバする?」
「...どっちやりたい?」
「どっちでも...」

とスタートから挙動不審
幸先の悪いスタートとなりました。

今回チームじゃけぇが開発合宿で開発した成果物と選定した技術スタック

今回チームじゃけぇが開発合宿で開発したのは...

React×Laravel(API)×Dockerを利用したある分野に特化した専用掲示板!!

※正式な公表のタイミングがあると思うので名前はあえて控えます

フロントエンド: React (じゃけぇ担当)
サーバサイド: Laravel API (はる・かっぽ担当)

今回のソースコードのフォルダ構成ですが、ReactとLaravelを同じ階層のリポジトリに置き、開発環境はDockerを利用、本番環境のデプロイ先はフロント・サーバそれぞれのサーバという構成でWebサービスを作りました。(この構成、個人的にすごくやりやすかったです)
余裕があればGitHub共有したいと思います!

Dockerについて

フロントのDockerはcreate-react-appを参考に
サーバのDockerはphp-for-everyoneを参考に
フロント・サーバの各々のDockerの良さを引っ張ってきて、つなぎこんでガッチャンコした
今回特別に作ったDockerを使用しました。
GitHubについては、落ち着いたらリポジトリとは別にReact×Laravel(API)×Dockerの環境構築用としてDocker環境を共有する予定です。
Facebookの皆さん、Laravel-shibuyaの皆さん 参考にさせていただきました。ありがとうございます。)

本番サーバについて

ReactはNow
LaravelはHerku
のサーバを利用しました。
Laravelは完全にAPIとし、DBの値やビジネスロジックでゴニョゴニョした値をJSON型で返す処理のみで、データ表示はReactにすべてお任せました。
デプロイは、masterブランチにmergeされたと同時に自動で本番反映されるように設定致しました。

17:00~ チームじゃけぇ始動

それぞれの役割も決まり、チームじゃけぇもいざ開発スタートです!

当日までに、はるさんがWebサービスのデザインをFigmaで作成していただいていたのと、じゃけぇさんの技術力でフロントは初速充分でバリバリ進みます。

肝心のサーバサイドはというと...

私自身、普段PHPのSymfonyを使用しており、Laravelの業務経験はありましたが約一年ぶりに触ります。
はるさんも普段はJavaを使った開発が多いとのことで

「ヤベェ、どうします?w」

「まずはAPIの設定から?」

とあたふた。

しかし、人間の記憶とは素晴らしいもので、一度触り始めると1年前のLaravelの記憶がどんどん蘇ってきました。
まさに、「書けるっ!書けるぞっ!!」状態

はるさんも吸収力がナプキンレベル、1つ進めると後は自走状態に。

そこからは3人とも、時間を忘れるように開発に没頭しました。

20:00~ 晩御飯

今回の合宿の晩御飯は豪華!
宅配のピザLsize3枚(チーズ・照り焼き・マヨポテト)
寿司を5人前(サーモンセット3人前・マグロセット2人前)
お寿司の注文にはUberEatsを利用しました。

20:00過ぎに全ての注文が届き、支払いも済ませたので食事にしましょうと皆さん一休み。
いざ食べようと広げてみると...

「あれ?マグロセット2人前なくね?」

どういうことか、支払いはお寿司5人前分したのに注文したマグロセット2人前が配達されませんでした。
なにしとんねんUberEats
IMG_0702.JPG

21:00~ 再び事件

ご飯も食べ終えたので開発する人部屋に残り、銭湯行く人は行きましょうということになりました。
私とはるさんは再び開発を進め、じゃけぇさんは銭湯に。

ここでまたまた事件発生

なんと、突然フロントが表示されない!!!

しかも、フロント担当のじゃけぇさんが銭湯に行ってしまっていません。

ドヤ顔で
「yarn install したら治るでしょ」 と高を括っていました。

が、インストールしても

「あれ?治らない、、、」

結局、はるさんと1時間ほど格闘しました。

じゃけぇさんが帰ってきて解決しましたが、
結論、yarn install の場所を間違えていました。

しょうもないことで時間取られてしまう エンジニアあるあるですよね。

これにより、フロント頼りの開発を辞め、API開発時に便利なGoogleChromeの拡張ツールTalend Api Tester
を使いこなせるようになりました。(いや、使ってなかったんかい!)

22:00~6:00 空白の8時間

ふと時計を見るともう6時。

ほとんど記憶がございません。
意識朦朧の中、必死で実装しまくってました。

結果的には、
フロント側は基本的なフォーム作成やデザイン実装から、ストレージを利用したデータ保存機能まで。
サーバ側はAPIでのRouting・基本的なCRUD処理からLaravelのEloquentを利用したソート切り替え処理まで。

難なくクリアし、どちらともキリの良いところで実装を終えられました。万歳。

8:00~ 成果物発表

やはり、一晩で3人で1つのWebサービスを作り上げるのは至難の業。
結論を言うと、3チームとも時間の問題もあり、完成に至らずでした。
しかし、全員が触ったことのない新しい技術に挑戦するといった目標を掲げ最後まで諦めずに頑張るチーム
Laravelの認証周りの理解に苦しみながらも様々な記事から豊富な知識を蓄えたチーム等、
どのチームも開発に没頭し、誰一人脱落することなく開発合宿を終えることができました!

成果物発表が終わったあとは眠さの限界でチェックアウトの時間まで床で爆睡。
私一人だけ、昨日の残りのピザの残飯処理をすると言うカオスな光景となりました。
IMG_0704.JPG

まとめ

以上、今回の大阪エンジニア開発合宿(OsakaDevelopmentCamp)の個人的レポートでした。
個人的には、様々なトラブルを乗り越えぶっ通しで久々にLaravel触れることができて大変嬉しかったです!
貴重な体験をさせていただきまして、主催者の並里氏をはじめ参加された皆様、ありがとうございました!
そしてお疲れ様でした!
次回開催はいつになるかわかりませんが大いに楽しみですね?
IMG_0709.JPG
(疲れ切った表情の皆さんを載せるのは心が痛かったのでマンウィズっぽく)

有志ですがプロダクト参加者募集してます

今回実装した掲示板Webサービスですが React×Laravel(API)×Docker で環境構築されており、プロダクト自体も初学者に大変わかりやすく勉強になるプロダクトだと自負しております。
3人とも完全に趣味の範囲でやっておりますので、お給料等をお支払いすることはできませんが、もしこのプロダクトに参加して一緒にLaravel・Reactの勉強をしたり自分のポートフォリオの一つとして利用したいというエンジニアの方(実務未経験でも可)いらっしゃいましたら気軽にDM・リプでご連絡くださいませ〜
一緒に楽しくWebサービスを作りましょう?

最後までお読みいただきありがとうございました〜?

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

開発合宿でReact×Laravel(API)×Dockerを利用したWebサービスを作ったお話

はじめに

初めまして、大阪でWebエンジニアをしているかっぽと申します。
今回、主催者の並里氏のお誘いもあり大阪で行われた一泊二日のエンジニア合宿に参加してきたのですが
思っていた以上に刺激的で有意義な時間を過ごせましたので記事にしようと思い書いている次第です。
こちらの記事は合宿についての自分チーム主体の偏見の塊のような個人的共有レポートです。

第1回大阪エンジニア開発合宿(OsakaDevelopmentCamp)とは

2020/02/22(土) 〜 2020/02/23(日) に大阪の難波周辺で行われたエンジニアの開発合宿
Laravelのもくもく会や勉強会、ハンズオンなど多くのエンジニアのイベントを企画しているナミザト氏の今度開発合宿やってみたいな〜というぽっとでのツイートをきっかけに賛同したフットワーク軽めのエンジニア9人が集まり、3人1チームとなって前日から次の日の朝まで眠らずにひとつWebサービスを開発するというエンジニアにとって夢のような合宿です

前置き

今回の開発合宿の参加者

チームサイトウ

チームアマゾネス

チームじゃけぇ

合宿日時

2020/02/22(土) 16:00 〜 2020/02/23(日) 10:00

当日の予定

当日はチームで一つの成果物(web/アプリ問わない)を23日の7時までに作成して、
23日の8時にはみんなの前でそれぞれ成果物を発表する

合宿のルール

  • 技術選定はチームで話し合い決定する
  • 成果物はチームで話し合い決定する
  • 開発終了後の成果物の所有等はチームで話し合い決定する(自由)

今回の合宿、開始日までに環境構築や事前準備はOKですが、実装は開始日の16:00からしか行ってはいけないという暗黙のルールがありました。
しかし、なんと3チーム中2チームが16:00以前から実装を進めていたとの情報が!!(ずるい)

16:30~ 合宿開始

そんなこんなで始まった開発合宿ですが、さすが有名なエンジニアさんが多く集まっているだけあって、始まったとたんからバリバリと実装を開始しました。(私のチーム以外は。)
IMG_0706.JPG

ふんわりとしか役割を決めていなかった私のチーム、チームじゃけぇはその姿を見て呆然とし、

「え、あ、フロントする?サーバする?」
「...どっちやりたい?」
「どっちでも...」

とスタートから挙動不審
幸先の悪いスタートとなりました。

今回チームじゃけぇが開発合宿で開発した成果物と選定した技術スタック

今回チームじゃけぇが開発合宿で開発したのは...

React×Laravel(API)×Dockerを利用したある分野に特化した専用掲示板!!

※正式な公表のタイミングがあると思うので名前はあえて控えます

フロントエンド: React (じゃけぇ担当)
サーバサイド: Laravel API (はる・かっぽ担当)

今回のソースコードのフォルダ構成ですが、ReactとLaravelを同じ階層のリポジトリに置き、開発環境はDockerを利用、本番環境のデプロイ先はフロント・サーバそれぞれのサーバという構成でWebサービスを作りました。(この構成、個人的にすごくやりやすかったです)
余裕があればGitHub共有したいと思います!

Dockerについて

フロントのDockerはcreate-react-appを参考に
サーバのDockerはphp-for-everyoneを参考に
フロント・サーバの各々のDockerの良さを引っ張ってきて、つなぎこんでガッチャンコした
今回特別に作ったDockerを使用しました。
GitHubについては、落ち着いたらリポジトリとは別にReact×Laravel(API)×Dockerの環境構築用としてDocker環境を共有する予定です。
Facebookの皆さん、Laravel-shibuyaの皆さん 参考にさせていただきました。ありがとうございます。)

本番サーバについて

ReactはNow
LaravelはHerku
のサーバを利用しました。
Laravelは完全にAPIとし、DBの値やビジネスロジックでゴニョゴニョした値をJSON型で返す処理のみで、データ表示はReactにすべてお任せました。
デプロイは、masterブランチにmergeされたと同時に自動で本番反映されるように設定致しました。

17:00~ チームじゃけぇ始動

それぞれの役割も決まり、チームじゃけぇもいざ開発スタートです!

当日までに、はるさんがWebサービスのデザインをFigmaで作成していただいていたのと、じゃけぇさんの技術力でフロントは初速充分でバリバリ進みます。

肝心のサーバサイドはというと...

私自身、普段PHPのSymfonyを使用しており、Laravelの業務経験はありましたが約一年ぶりに触ります。
はるさんも普段はJavaを使った開発が多いとのことで

「ヤベェ、どうします?w」

「まずはAPIの設定から?」

とあたふた。

しかし、人間の記憶とは素晴らしいもので、一度触り始めると1年前のLaravelの記憶がどんどん蘇ってきました。
まさに、「書けるっ!書けるぞっ!!」状態

はるさんも吸収力がナプキンレベル、1つ進めると後は自走状態に。

そこからは3人とも、時間を忘れるように開発に没頭しました。

20:00~ 晩御飯

今回の合宿の晩御飯は豪華!
宅配のピザLsize3枚(チーズ・照り焼き・マヨポテト)
寿司を5人前(サーモンセット3人前・マグロセット2人前)
お寿司の注文にはUberEatsを利用しました。

20:00過ぎに全ての注文が届き、支払いも済ませたので食事にしましょうと皆さん一休み。
いざ食べようと広げてみると...

「あれ?マグロセット2人前なくね?」

どういうことか、支払いはお寿司5人前分したのに注文したマグロセット2人前が配達されませんでした。
なにしとんねんUberEats
IMG_0702.JPG

21:00~ 再び事件

ご飯も食べ終えたので開発する人部屋に残り、銭湯行く人は行きましょうということになりました。
私とはるさんは再び開発を進め、じゃけぇさんは銭湯に。

ここでまたまた事件発生

なんと、突然フロントが表示されない!!!

しかも、フロント担当のじゃけぇさんが銭湯に行ってしまっていません。

ドヤ顔で
「yarn install したら治るでしょ」 と高を括っていました。

が、インストールしても

「あれ?治らない、、、」

結局、はるさんと1時間ほど格闘しました。

じゃけぇさんが帰ってきて解決しましたが、
結論、yarn install の場所を間違えていました。

しょうもないことで時間取られてしまう エンジニアあるあるですよね。

これにより、フロント頼りの開発を辞め、API開発時に便利なGoogleChromeの拡張ツールTalend Api Tester
を使いこなせるようになりました。(いや、使ってなかったんかい!)

22:00~6:00 空白の8時間

ふと時計を見るともう6時。

ほとんど記憶がございません。
意識朦朧の中、必死で実装しまくってました。

結果的には、
フロント側は基本的なフォーム作成やデザイン実装から、ストレージを利用したデータ保存機能まで。
サーバ側はAPIでのRouting・基本的なCRUD処理からLaravelのEloquentを利用したソート切り替え処理まで。

難なくクリアし、どちらともキリの良いところで実装を終えられました。万歳。

8:00~ 成果物発表

やはり、一晩で3人で1つのWebサービスを作り上げるのは至難の業。
結論を言うと、3チームとも時間の問題もあり、完成に至らずでした。
しかし、全員が触ったことのない新しい技術に挑戦するといった目標を掲げ最後まで諦めずに頑張るチーム
Laravelの認証周りの理解に苦しみながらも様々な記事から豊富な知識を蓄えたチーム等、
どのチームも開発に没頭し、誰一人脱落することなく開発合宿を終えることができました!

成果物発表が終わったあとは眠さの限界でチェックアウトの時間まで床で爆睡。
私一人だけ、昨日の残りのピザの残飯処理をすると言うカオスな光景となりました。
IMG_0704.JPG

まとめ

以上、今回の大阪エンジニア開発合宿(OsakaDevelopmentCamp)の個人的レポートでした。
個人的には、様々なトラブルを乗り越えぶっ通しで久々にLaravel触れることができて大変嬉しかったです!
貴重な体験をさせていただきまして、主催者の並里氏をはじめ参加された皆様、ありがとうございました!
そしてお疲れ様でした!
次回開催はいつになるかわかりませんが大いに楽しみですね?
IMG_0709.JPG
(疲れ切った表情の皆さんを載せるのは心が痛かったのでマンウィズっぽく)

有志ですがプロダクト参加者募集してます

今回実装した掲示板Webサービスですが React×Laravel(API)×Docker で環境構築されており、プロダクト自体も初学者に大変わかりやすく勉強になるプロダクトだと自負しております。
3人とも完全に趣味の範囲でやっておりますので、お給料等をお支払いすることはできませんが、もしこのプロダクトに参加して一緒にLaravel・Reactの勉強をしたり自分のポートフォリオの一つとして利用したいというエンジニアの方(実務未経験でも可)いらっしゃいましたら気軽にDM・リプでご連絡くださいませ〜
一緒に楽しくWebサービスを作りましょう?

最後までお読みいただきありがとうございました〜?

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

AWSのアカウント作った直後の状態からECS+Fargateでコンテナを起動する

超・初心者向け、AWSのアカウント作った直後の状態からECS+Fargateでコンテナを起動するまで。
最低限、AWSのマネジメントコンソールをちょこちょこでも触ったことがあるくらいが前提。

全体の流れ。
1. EC2の起動
2. Dockerのインストール
3. セキュリティグループの設定
4. Tomcatの起動
5. CLIの設定
6. DockerコンテナのイメージをECRに登録
7. IAMポリシーとロールの設定
8. ECS on FargateでECRに登録したDockerコンテナのイメージを起動

1. EC2の起動 ~ 2. Dockerのインストール

↓この辺の記事を参考にして、EC2でインスタンスを起動してDockerをインストールする
【Qiita】AWSのEC2でDockerを試してみる

3. セキュリティグループの設定 ~ 4. DockerでTomcatの起動

↓この辺の記事を参考にして、DockerでTomcatを起動する。
【Qiita】Docker上でnginx+tomcat を構築してみる。

当たり前だが、セキュリティグループでこの辺で使うポートを開放しておかないと通らない。

5. CLIの設定

さてDockerコンテナをレジストリに登録するぞ!と思ってもまだ早い。まずはCLIを使えるようにしておかないと、aws ecr のコマンドが実行できない。
今回は、AWS標準のAMIからEC2インスタンスを起動しているので、CLIはデフォルトでインストール済み。↓これを参考にしながら、初期設定を行う。IAMユーザの登録もこの中で説明されている。
【AWS公式】AWS CLI の設定

6. DockerコンテナのイメージをECRに登録

↓を見ながら作ってきたDockerコンテナのイメージをECRにPUSHする。
【Qiita】AWS ECRにdockerイメージを登録する

7. IAMポリシーとロールの設定

さて、いよいよECS on Fargateでデプロイだ!と思ったけどちょっと待って。
ECSを実行するためのIAMポリシーとロールを設定しないと、コンテナを起動することができないのである。
【AWS公式】Amazon ECS タスク実行 IAM ロール

8. ECS on FargateでECRに登録したDockerコンテナのイメージを起動

↓この辺を参考にしながら、タスク定義→クラスタ作成→サービス作成をしてする。
【Qiita】Amazon Fargate でコンテナを動かす

やったーこれで動くはずだ!と思ったら、ALBからコンテナへのヘルスチェックが上手く通らず、Bad Gatewayになってしまう。うーむ、よく分からない……。ここからもう少し改善をしてみたかったのだが……。

その他

Dockerのログ確認

試行錯誤しているうちに docker run してもコンテナが起動しない(正確には、おそらく起動後にexitしていたのだと思う)ことがあり、↓この辺をテキトーにやって調べたり直したりはした。
【Qiita】dockerでコンテナが立ち上がらないときやってみること

タスク定義の削除

ECSのタスク定義を登録すると、簡単に消すことができなくなる。
↓これで消せる。厳密にはINACTIVEにして見えなくしているだけのようだ。完全に消し去ることはできなそう?
【Qiita】タスク定義の登録解除

サービスディスカバリからのサービス名の削除

どうにも、サービスディスカバリに登録したサービスが上手く削除できず、次に同じサービス名でサービス起動しようと思うと重複エラーになってしまう。ちゃんと全部掃除しているはずなのだが、一覧の取得の仕方も分からず……

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

AWSのアカウント作った直後の状態からECS+FargateでTomcatのDockerコンテナを起動する

超・初心者向け、AWSのアカウント作った直後の状態からECS+FargateでTomcatのDockerコンテナを起動するまで。
最低限、AWSのマネジメントコンソールをちょこちょこでも触ったことがあるくらいが前提。

全体の流れ。
1. EC2の起動
2. Dockerのインストール
3. セキュリティグループの設定
4. Tomcatの起動
5. CLIの設定
6. DockerコンテナのイメージをECRに登録
7. IAMポリシーとロールの設定
8. ECS on FargateでECRに登録したDockerコンテナのイメージを起動

1. EC2の起動 ~ 2. Dockerのインストール

↓この辺の記事を参考にして、EC2でインスタンスを起動してDockerをインストールする
【Qiita】AWSのEC2でDockerを試してみる

EC2へのTelnetログインどうやんねん、って人は↓これを読む。
【AWS公式】PuTTY を使用した Windows から Linux インスタンスへの接続

3. セキュリティグループの設定 ~ 4. DockerでTomcatの起動

↓この辺の記事を参考にして、DockerでTomcatを起動する。
【Qiita】Docker上でnginx+tomcat を構築してみる。

当たり前だが、セキュリティグループでこの辺で使うポートを開放しておかないと通らない。

5. CLIの設定

さてDockerコンテナをレジストリに登録するぞ!と思ってもまだ早い。まずはCLIを使えるようにしておかないと、aws ecr のコマンドが実行できない。
今回は、AWS標準のAMIからEC2インスタンスを起動しているので、CLIはデフォルトでインストール済み。↓これを参考にしながら、初期設定を行う。IAMユーザの登録もこの中で説明されている。
【AWS公式】AWS CLI の設定

6. DockerコンテナのイメージをECRに登録

↓を見ながら作ってきたDockerコンテナのイメージをECRにPUSHする。
【Qiita】AWS ECRにdockerイメージを登録する

7. IAMポリシーとロールの設定

さて、いよいよECS on Fargateでデプロイだ!と思ったけどちょっと待って。
ECSを実行するためのIAMポリシーとロールを設定しないと、コンテナを起動することができないのである。
【AWS公式】Amazon ECS タスク実行 IAM ロール

8. ECS on FargateでECRに登録したDockerコンテナのイメージを起動

↓この辺を参考にしながら、タスク定義→クラスタ作成→サービス作成をする。
【Qiita】Amazon Fargate でコンテナを動かす

気を付けなければいけないのは「ポートマッピングの設定」で、Tomcatは80番ポートを起動することができないので、ポートマッピングでコンテナ側のポートを8080にしないといけない。

やったーこれでTomcat起動したぞー!あとは、応用すれば色々起動できるようになるはず。

その他

Dockerのログ確認

試行錯誤しているうちに docker run してもコンテナが起動しない(正確には、おそらく起動後にexitしていたのだと思う)ことがあり、↓この辺をテキトーにやって調べたり直したりはした。
【Qiita】dockerでコンテナが立ち上がらないときやってみること

Dockerイメージの掃除

色々と docker run とかやってると、docker images したときに謎のイメージが増殖したりしているので、↓これを参考にキレイにした。別にVMなんだから後生大事にせず潰せばいいんだけどね…。
【Qiita】Dockerイメージとコンテナの削除方法

タスク定義の削除

ECSのタスク定義を登録すると、簡単に消すことができなくなる。
↓これで消せる。厳密にはINACTIVEにして見えなくしているだけのようだ。完全に消し去ることはできなそう?
【Qiita】タスク定義の登録解除

サービスディスカバリからのサービス名の削除

どうにも、サービスディスカバリに登録したサービスが上手く削除できず、次に同じサービス名でサービス起動しようと思うと重複エラーになってしまう。ちゃんと全部掃除しているはずなのだが、一覧の取得の仕方も分からず……

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

Dockerで環境を立ちあげるための手順(個人用メモ)

はじめに

本稿は、Dockerで環境を立ち上げる際の手順を自分のために書き起こしたものです。このような面倒な手順を踏まないとDockerコマンドを実行できないのは筆者だけかもしれませんが、個人用メモなので悪しからず。なお、本稿においては事前に環境を作成済みであることを前提にしております。

筆者の環境は、以下の通りです。

  • Docker Toolbox v19.03.1 (Windows 64bit)
  • Git Bash

Dockerを立ち上げる手順

最初に、docker-machineの状態を確認します。

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL   SWARM   DOCKER    ERRORS
default   -        virtualbox   Stopped                 Unknown

上記の出力結果から、

1."default"というdocker-machineが存在し、
2.Activeではない、かつ
3.Stateが"Stopped"であることが分かります。

したがって、まず"default"をStartさせます。

$ docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. 
Sometimes, such confirmation window is minimized in the taskbar.
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

次に、"default"をActiveにします。
これには、evalコマンドを使います。

$ eval "$(docker-machine env default)"

"default"がActiveになったことを確かめるために、再び一番最初のコマンドを入力します。

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v19.03.5

"default"のSTATEがrunningになっています。また、Activeの欄に"*"がついており、Activeになっていることも分かります。
これでdocker-machineをActiveにする作業が完了しました。

次に、dockerのContainerをstartさせます
まず、現状あるContainerの状態を確認します。

$ docker ps -a
CONTAINER ID        IMAGE           COMMAND                  CREATED       STATUS                     PORTS                  NAMES
9c68b6037143        1a7             "jupyter lab --ip=0.…"   29 hours ago        Exited (255) 5 minutes ago   0.0.0.0:8888->8888/tcp   my-first-lab

my-first-labというコンテナが存在している(runはしていない)ことが分かります。5分前にExitされたようです。
このContainerをStartさせます。

$ docker start my-first-lab
my-first-lab

これで環境を立ち上げる作業が完了しました。
筆者の場合は、これでJupyterLabの作業環境にアクセスすることができます。
JupyterLab.png

おわりに

本稿が初めてQiitaに投稿した記事になりますが、意外とサクサク書けて楽しかったです(ただの感想)。この記事が誰かの役に立つことを願っております。

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

Docker + Haskell の Hello Worldビルド

Dockerの中で Haskell をビルドして、Hello World することがゴールです。
手順をシンプルに書いていきます。

まず Docker と Docker-compose を入れておきます。これは省略します。

Dockerディレクトリを作成

以下のようにファイルを作ります。

./docker
./docker/.env
./docker/docker-compose.yml
./docker/haskell
./docker/haskell/Dockerfile

./src/
./src/haskell

Dockerの設定

Docker全体用の設定

今回はコンテナは1つしか作りませんが、
今後の拡張を考えたつくりにはしておきます。
常にクセづけておくことで、迷うことがなくなります。

.env
COMPOSE_PROJECT_NAME=haskell-docker-starter

Haskellビルド用コンテナ

docker-compose.yml
version: '3'
services:

  haskell:
    build: ./haskell
    container_name: '${COMPOSE_PROJECT_NAME}-haskell'
    tty: true
    volumes:
      - "../src/haskell:/opt/src"
Dockerfile
FROM centos:centos7

RUN curl -sSL https://get.haskellstack.org/ | sh

# stackインストール
RUN stack upgrade
RUN stack --version

# stack の初期設定
RUN stack setup

バージョン表示もいれておくと、ビルド時に確かめられて便利です。

Dockerコンテナ作成

cd ./docker
docker-compose build
docker-compose up -d

これで Dockerコンテナが起動します。
docker-compose build せずとも、 up -d だけでもビルド一緒にしてくれているのですが、
それは気を利かせてくれているだけなので、動きを理解するためにも build してみましょう。

Haskell の初期プロジェクト作成

docker exec -it haskell-docker-starter-haskell bash

# 以下 Docker の中
cd /opt/src
stack new sample-project

これにより、
./src/haskell/sample-project
というフォルダができ、中にたくさんのファイル群ができています。

ちなみに Dockerコンテナ内からは、 /opt/src/sample-project でアクセスできます。

sample-project のビルド

初期処理

stack init が必要です。
ホストOS以下のコマンドを実行すれば Docker内で stack init が動作します。

docker exec haskell-docker-starter-haskell bash -c "cd /opt/src && stack init"

ビルド

変更する度に行うビルドです。

docker exec haskell-docker-starter-haskell bash -c "cd /opt/src && stack build"

どこかに実行ファイルができています。
なにかわかったら追記します。

実行

docker exec haskell-docker-starter-haskell bash -c "cd /opt/src/sample-project && stack exec sample-project-exe"
# 出力結果: someFunc

これはなにかのファイルを読んで、実行パスを探してくれているみたいです。
なにかわかったら追記します。

ソースコード編集

./src/haskell/sample-project/src がソースコードのようです。

Lib.hs
module Lib
    ( someFunc
    ) where

someFunc :: IO ()
someFunc = putStrLn "someFunc"

"someFunc" をとりあえず "Hello World" に変更します。

そして ビルド、実行

docker exec haskell-docker-starter-haskell bash -c "cd /opt/src && stack build"
docker exec haskell-docker-starter-haskell bash -c "cd /opt/src/sample-project && stack exec sample-project-exe"
# 出力結果: Hello World

これでホストOSの環境をいじらずに Haskell をビルド、実行することができました。

github

https://github.com/dd0125/haskell-docker-starter

参考

Stackでやる最速Haskell Hello world! (GHCのインストール付き!)
https://qiita.com/igrep/items/da1d8df6d40eb001a561

ありがとうございます。

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

Jetson Nano に Docker & docker-compose をインストールする方法

1. はじめに

今回は、自分自身への備忘録を兼ねて、Jetson Nano に Docker & docker-compose をインストールする方法を、お伝えしたいと思います。

2. この記事を読んでできること

  • RJetson Nanoで Docker & docker-compose を使えるようになる。

3. 注意事項

  • Docker のアーキテクチャは、arm64(ARM 64ビット)版となります。

4. 必要なもの

  • Jetson Nano
  • インターネット環境

5. インストール済みの標準dockerの確認

  • dockerは標準インストール済みのようです。
  • ここでは、動作確認を済ませます。
コマンドプロンプト
// dockerのバージョン確認(dockerは標準でインストールされているみたいです)
$ docker -v
Docker version 18.09.7, build 2d0083d

// 自分のユーザをdockerグループに追加
sudo gpasswd -a $USER docker

// dockerの再起動
sudo systemctl restart docker.service

// 接続を一度閉じてから、再接続する
exit

6. docker-composeのインストール

  • docker-composeのインストールをインストールします。
コマンドプロンプト
// ディレクトリ移動
$ cd /opt

// curlのインストール
$ sudo apt -y install curl

// pythonバージョンの確認
$ python --version
Python 2.7.17

// パッケージのアップデート
$ sudo apt update

// pipのインストール
$ curl -sSL https://bootstrap.pypa.io/get-pip.py | sudo python

// pipバージョンの確認
$ pip --version
pip 20.0.2 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7)

// 必要ライブラリのインストール
$ sudo apt -y install libffi-dev python-openssl libssl-dev

// 環境変数の設定
$ export DOCKER_COMPOSE_VERSION=1.24.0

// docker-composeのインストール
$ sudo pip install docker-compose=="${DOCKER_COMPOSE_VERSION}"

// docker-composeのバージョン確認
$ docker-compose -v
docker-compose version 1.24.0, build 0aa5906

7. dockerの動作確認

コマンドプロンプト
// OS再起動(念のため)
$ sudo shutdown -r now

// dockerの実行(ハローワールド)
$ docker run --rm hello-world

8. docker-composeの動作確認

  • docker-compose.ymlファイルを作成し、ファイル保存する。
docker-compose.yml
version: "2"

services:
  app:
    image: hello-world

  • docker-composeを実行する。
コマンドライン
// docker-compose.ymlファイルが存在することを事前確認
$ ls
docker-compose.yml

// docker-composeを実行
$ sudo docker-compose up

9. 参考:Dockerコマンド、docker-composeコマンド

10. おわりに

いかがでしたでしょうか?意外と簡単にDocker & docker-composeをはじめることができたのではないかなと思います。
今回の記事が、みなさまの学習の参考になれば幸いです。

2020/02/24 TAKAHIRO NISHIZONO

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

Redash を Docker for Mac で最速で動かす

概要

Redash の Docker for Mac 上で最速で動かします。
Redash の開発はしないので、用意されたセットアップを実行するだけになります。
セットアップファイルの実行から Redash の起動までに少し修正が必要でした。

環境

macOS 10.15.3 Catalina
Docker for Mac 2.2.0.3
Redash v8.0.0.b32245

ディレクトリ構成

setup ディレクトリは、公式から git clone してきたもの。
その中の setup.sh を実行すると、redash ディレクトリが作成されます。

setup/
  ├ setup.sh
redash/
  ├ postgres-data/
  ├ env
  ├ docker-compose.yml

事前準備

setup.sh で pwgen, wget が必要なので予めインストールしておきます

$ brew install pwgen
$ brew install wget

手順

セットアップファイルをとってくる

$ git clone git@github.com:getredash/setup.git

セットアップファイルの中にある setup.sh を編集

とってきた setup.sh は Ubuntu 用なので、Mac で動くように編集する

もとのファイルから変更している箇所は
- Redash のディレクトリ作成箇所
- 不要な Docker インストールの削除
- 不要な sudo 削除
- sed が Mac で動くように修正
- docker-compose は手動でやるのでコメントアウト
あたりです。
もとのセットアップファイルは /opt/redash に作成しようとしていますが
Mac上では、自分の好きなディレクトリに設置したいので変更します。
今回はこの setup ディレクトリと同じ階層にしました。

setup.sh
#!/usr/bin/env bash
# This script setups dockerized Redash on Mac OS.
set -eu

REDASH_BASE_PATH=../redash

create_directories() {
    if [[ ! -e $REDASH_BASE_PATH ]]; then
        mkdir -p $REDASH_BASE_PATH
        chown $USER $REDASH_BASE_PATH
    fi

    if [[ ! -e $REDASH_BASE_PATH/postgres-data ]]; then
        mkdir $REDASH_BASE_PATH/postgres-data
    fi
}

create_config() {
    if [[ -e $REDASH_BASE_PATH/env ]]; then
        rm $REDASH_BASE_PATH/env
        touch $REDASH_BASE_PATH/env
    fi

    COOKIE_SECRET=$(pwgen -1s 32)
    SECRET_KEY=$(pwgen -1s 32)
    POSTGRES_PASSWORD=$(pwgen -1s 32)
    REDASH_DATABASE_URL="postgresql://postgres:${POSTGRES_PASSWORD}@postgres/postgres"

    echo "PYTHONUNBUFFERED=0" >> $REDASH_BASE_PATH/env
    echo "REDASH_LOG_LEVEL=INFO" >> $REDASH_BASE_PATH/env
    echo "REDASH_REDIS_URL=redis://redis:6379/0" >> $REDASH_BASE_PATH/env
    echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> $REDASH_BASE_PATH/env
    echo "REDASH_COOKIE_SECRET=$COOKIE_SECRET" >> $REDASH_BASE_PATH/env
    echo "REDASH_SECRET_KEY=$SECRET_KEY" >> $REDASH_BASE_PATH/env
    echo "REDASH_DATABASE_URL=$REDASH_DATABASE_URL" >> $REDASH_BASE_PATH/env
}

setup_compose() {
    REQUESTED_CHANNEL=stable
    LATEST_VERSION=`curl -s "https://version.redash.io/api/releases?channel=$REQUESTED_CHANNEL"  | json_pp  | grep "docker_image" | head -n 1 | awk 'BEGIN{FS=":"}{print $3}' | awk 'BEGIN{FS="\""}{print $1}'`

    cd $REDASH_BASE_PATH
    GIT_BRANCH="${REDASH_BRANCH:-master}" # Default branch/version to master if not specified in REDASH_BRANCH env var
    wget https://raw.githubusercontent.com/getredash/setup/${GIT_BRANCH}/data/docker-compose.yml
    sed -Ei '' "s/image: redash\/redash:([A-Za-z0-9.-]*)/image: redash\/redash:$LATEST_VERSION/" docker-compose.yml
    # echo "export COMPOSE_PROJECT_NAME=redash" >> ~/.profile
    # echo "export COMPOSE_FILE=/opt/redash/docker-compose.yml" >> ~/.profile
    # export COMPOSE_PROJECT_NAME=redash
    # export COMPOSE_FILE=/opt/redash/docker-compose.yml
    # docker-compose run --rm server create_db
    # docker-compose up -d
}

create_directories
create_config
setup_compose

docker-compose.yml を編集

  • 生成された docker-compose.yml で /opt/redash となっている箇所を . に差し替える(setup.sh で Redash のディレクトリ作成箇所を変えたため)
  • restart : always を消す(必須ではない)
  • nginx の ports を 8080:80 にする(必須ではない)
docker-compose.yml
version: "2"
x-redash-service: &redash-service
  image: redash/redash:8.0.0.b32245
  depends_on:
    - postgres
    - redis
  env_file: ./env
services:
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
  scheduler:
    <<: *redash-service
    command: scheduler
    environment:
      QUEUES: "celery"
      WORKERS_COUNT: 1
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
  redis:
    image: redis:5.0-alpine
  postgres:
    image: postgres:9.6-alpine
    env_file: ./env
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
  nginx:
    image: redash/nginx:latest
    ports:
      - "8080:80"
    depends_on:
      - server
    links:
      - server:redash

起動

$ docker-compose run --rm server create_db
$ docker-compose up -d

接続

http://localhost:8080 にアクセスして、この画面が出てきたら成功
スクリーンショット 2020-02-24 16.12.28.png

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

MySQL Sample DatabaseのデータをローカルのDockerコンテナで立てたMySQLに反映させる方法

ここの「Download MySQL Sample Database」からmysqlsampledatabase.sqlをダウンロードします。

以下のようなテーブルが作成できます

ダウンロードした.sqlファイルをdocker/db/sqlにコピーします。あとは立ち上げるだけで.sqlのデータがDBに反映されます。ファイル構成はこちらを参考にしていただくと簡単に構築できると思います。

コンテナ内のmysqlにログインするには以下を実行するのが楽です。

docker exec -it (docker ps -q) mysql -u root -p -D <database> -P <mysql_port>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose for wordpress と php.ini の設定

はじめに

Mac local に Wordpress の動作環境を作る必要があったのでどの方法が良いか検討したところ、docker-compose でやるのが一番手っ取り早いと思った。

docker-compose.yml の sample がdocker のドキュメント に載っていたので、ほぼほぼそのまま使わせていただくことにした。

が、起動してみると、テーマのアップロードができなかった。原因を調べたところ、php.ini の設定項目追加が必要だった。次回以降のためにメモ。

作業ログ

docker-compose.yml sample

まずは(ほぼほぼ)サンプルのまま起動してみる

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: wordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:5.3.2-php7.2-apache
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

docker-compose up して

$ docker-compose up -d
Creating network "wordpress_default" with the default driver
Creating volume "wordpress_db_data" with default driver
Creating wordpress_db_1 ... done
Creating wordpress_wordpress_1 ... done

ブラウザでアクセス

http://localhost:8000/

とりあえずログインまでは問題なし

Screen Shot 2020-02-20 at 14.53.41.png

テーマをアップロードしてみる

Screen Shot 2020-02-20 at 14.55.12.png

The link you followed has expired.

が、エラー

Screen Shot 2020-02-20 at 14.55.21.png

エラーメッセージは以下

  • The link you followed has expired.
  • 辿ったリンクは期限が切れています。

このエラーは php.ini に以下の設定を入れることで解消できた

設定の入った Docker image を使いたいので build する

Dockerfile ①

FROM wordpress:5.3.2-php7.2-apache

# set recommended PHP.ini settings
RUN { \
  echo 'max_execution_time=-1'; \
  echo 'memory_limit=-1'; \
  echo 'post_max_size=-1'; \
} > /usr/local/etc/php/conf.d/wp-recommended.ini

build

$ docker build -t my_wordpress:1 .

docker-compose.yml を修正して再トライ

$ docker-compose down && docker-compose up -d

どうかな?

残念ながらまたエラー

Screen Shot 2020-02-20 at 15.36.40.png

The uploaded file exceeds the upload_max_filesize directive in php.ini.

エラーメッセージは以下

  • The uploaded file exceeds the upload_max_filesize directive in php.ini.
  • アップロードしたファイルは php.ini で定義された upload_max_filesize を超過しています。

これはありがちなやつか

upload_max_filesize を追加

Dockerfile ②

FROM wordpress:5.3.2-php7.2-apache

# set recommended PHP.ini settings
RUN { \
  echo 'max_execution_time=-1'; \
  echo 'memory_limit=-1'; \
  echo 'post_max_size=-1'; \
  echo 'upload_max_filesize=100M'; \
} > /usr/local/etc/php/conf.d/wp-recommended.ini

build

$ docker build -t my_wordpress:2 .

今度はどうか

いけた!

Screen Shot 2020-02-20 at 15.41.48.png

おわり

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

どなたか Rails の System Test が得意な方、これをどうやったら解決できるかおしえてください

なにこれ

Docker Compose で Rails 6.0 を動かそうと思って、コードを書こうとしているのだけど、System テストがどうにもこうにも適切にうごかすことができません。おそらく System Test は Fail がきているだけなので Rails 側は適切に処理はしているのだと思いますが、Selenium 側が Rails(Puma) のサーバにアクセスできていないのではないかと思われます。もうかれこれ1日以上、この問題でスタックしております。どなたか知識をご教示ください。
Screenshot from 2020-02-24 15-13-20.png

コード

Dockerfile

FROM ruby:2.6-alpine

WORKDIR /usr/src/app

COPY Gemfile Gemfile.lock yarn.lock package.json ./

RUN apk update && \
    apk upgrade && \
    apk add --no-cache yarn tzdata libxml2-dev curl-dev make gcc libc-dev g++ imagemagick6-dev postgresql-client postgresql-dev chromium chromium-chromedriver udev && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    gem update --system && \
    bundle install && \
    yarn install  && \
    rm -rf /usr/local/bundle/cache/* /usr/local/share/.cache/* /var/cache/* /tmp/* && \
    apk del libxml2-dev curl-dev make gcc libc-dev g++ tzdata

Docker compose File

version: '3'

volumes:
  pg_data:
  redis_data:

networks:
  main:

services:
  pg:
    image: postgres:11-alpine
    restart: always
    networks:
      main:
    volumes:
      - pg_data:/var/lib/postgresql/data/
    environment:
      TZ: Asia/Tokyo
      DATABASE_HOST: db
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
      POSTGRES_DB: dev

  redis:
    container_name: myapp-redis
    networks:
      main:
    image: redis:4.0
    environment:
      TZ: Asia/Tokyo
    volumes:
      - redis_data:/var/lib/redis

  hub:
    image: selenium/hub:3.141.59-iron
    ports:
      - 4444:4444
    environment:
      TZ: Asia/Tokyo
    networks:
      - main
  chrome:
    image: selenium/node-chrome:3.141.59-iron
    depends_on:
      - hub
    environment:
      TZ: Asia/Tokyo
      HUB_HOST: hub
      HUB_PORT: 4444
    networks:
      main:

  web:
    build:
      context: ./
    ports:
      - 3000:3000
    volumes:
      - ./:/usr/src/app/     
    stdin_open: true
    tty: true
    environment:
      - TZ=Asia/Tokyo
    command: /bin/sh -c "rm -f /var/app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0' --early-hints"   
    depends_on:
      - pg
      - redis
    networks:
      main:
        aliases:
          - web

application_system_test_case.rb

require "test_helper"
require 'selenium-webdriver'
require 'capybara/rails'

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400], options: { url: "http://hub:4444/wd/hub" }
end

users_test.rb

require "application_system_test_case"

class UsersTest < ApplicationSystemTestCase
  setup do
    @user = users(:one)
  end

  test "visiting the index" do
    visit users_url
    assert_selector "h1", text: "Users"
  end  
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kubernetesで実践するクラウドネイティブDevOps -2章-

経緯

Kubernetesで実践するクラウドネイティブDevOpsという本を買ったので、実際に手を動かしていきたいと思います。

コンテナとかKubernetesを全然知らないわけではないのですが、雰囲気でやってる部分が多いので再確認する意味でもしっかりやっていきたいと思います。

1章も非常にエモくてよかったんですが、今回は実際に手を動かす2章からです。

環境

Hyper-V(win10Pro)に作ったUbuntu上でやってみます。Docker for Winでも十分できます。(個人的に手元の環境(特にレジストリ)に手を入れるのが好きではないので。。。)

  • OS:Ubuntu 18.04.3 LTS
  • MEM:5GB
  • CPU:4Core
  • SSD:20GB

2章 Kubernetes 最初の一歩

Dockerのインストール

公式手順通りに入れます。

バージョンを確認

$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

コンテナイメージの実行

サンプルイメージを実行してみましょう

$ docker container run -p 9999:8888 --name hello cloudnatived/demo:hello

コンテナをフォアグラウンドで動かしているのでこれでOKです。ブラウザでlocalhost:9999を開いてみましょう。

2020-02-23_17h47_40.png

無事動いてることを確認できました。Ctrl-Cでコンテナを停止できます。

デモアプリケーション

先ほど動かしたアプリケーションの中を見てみましょう。

gitで手元にcloneします。

$ git clone https://github.com/cloudnativedevops/demo.git
Cloning into 'demo'...
remote: Enumerating objects: 808, done.
remote: Total 808 (delta 0), reused 0 (delta 0), pack-reused 808
Receiving objects: 100% (808/808), 312.19 KiB | 222.00 KiB/s, done.
Resolving deltas: 100% (324/324), done.

demo/hello/main.go をエディタで開いてみましょう。

main.go
package main

import (
        "fmt"
        "log"
        "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, 世界")
}

func main() {
        http.HandleFunc("/", handler)
        log.Fatal(http.ListenAndServe(":8888", nil))
}

これは 8888/http で待ち受け、HTTPリクエストに対して "Hello, 世界" という文字列を返すプログラムです。
シンプルなコードですが、立派にHTTPサーバとして機能します。

コンテナのビルド

先ほどはコンテナイメージをダウンロードして実行しました。DVDを買ってきて再生したようなものです。

次は自分でイメージを作成してみます。まずは先ほど実行したサンプルアプリのDockerfileを見てみましょう。

demo/hello/Dockerfile がそれにあたります。

Dockerfile
FROM golang:1.11-alpine AS build

WORKDIR /src/
COPY main.go go.* /src/
RUN CGO_ENABLED=0 go build -o /bin/demo

FROM scratch
COPY --from=build /bin/demo /bin/demo
ENTRYPOINT ["/bin/demo"]

『マルチステージビルド』という手法が使われています。Goコンテナでは標準的な手法だそうです。

まず最初のステージでは、先ほど紹介したmain.goを公式のgolangイメージを使って/bin/demoというバイナリにビルドします。

AS buildbuild部分がビルドステージの名前です。

次のステージでは、Docker が準備した最小イメージ scratch を使って、buildステージで作成した/bin/demoを自身にコピーして実行しています。

最小限のコンテナイメージ

なんでそんなことするの?と思うかもしれませんが、最小イメージのコンテナを使うことで起動の速さや、脆弱性リスクの軽減などの効果が見込めます。

試しにCentOS、Ubuntu、Golangの公式コンテナイメージをPullしてサイズを確認してみました。

一番下のcloudnatived/demoが今回実行したコンテナイメージです。最小イメージを使うことで桁違いの軽さを実現できていることを確認できます。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              72300a873c2c        2 days ago          64.2MB
golang              latest              297e5bf50f50        10 days ago         803MB
centos              latest              470671670cac        5 weeks ago         237MB
cloudnatived/demo   hello               eeb7d1c2e2b7        17 months ago       6.49MB

docker image build の実行

それでは実際にbuildしてみましょう。helloディレクトリでやってます。

$ docker image build -t myhello .
Sending build context to Docker daemon  11.78kB
Step 1/7 : FROM golang:1.11-alpine AS build
1.11-alpine: Pulling from library/golang
9d48c3bd43c5: Pull complete
# 中略
Step 5/7 : FROM scratch
 --->
Step 6/7 : COPY --from=build /bin/demo /bin/demo
 ---> 1ada301d7816
Step 7/7 : ENTRYPOINT ["/bin/demo"]
 ---> Running in 34c534cf6e67
Removing intermediate container 34c534cf6e67
 ---> 7ab71d258907
Successfully built 7ab71d258907
Successfully tagged myhello:latest

docker images で確認しましょう

$ docker images myhello
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myhello             latest              7ab71d258907        2 minutes ago       6.5MB

ちゃんとありますね。

イメージの命名

コマンドのオプションとして指定した-t myhelloがコンテナイメージにつけた名前です。内部的にはImageIDという64桁のIDがそれぞれのコンテナに付与されています。(参考:dockerコマンドでのフルImageID確認方法)

先ほど作成したmyhelloイメージを実行してみましょう。

$ docker container run -p 9999:8888 myhello

ブラウザでlocalhost:9999を開いてみましょう。

2020-02-24_12h17_09.png

一緒ですよね。

本書では『練習問題として任意の文字列を出してみましょう!』とあるので、文言変えたりしてやってみましょう。

Goをより深く学習するための対話型のA Tour of Goもおススメみたいです。

イメージのプッシュ

作ったイメージを自分のリポジトリにプッシュしてみましょう。Docker HUBでDockerIDを取得し、ローカルのDockerデーモンと自分のDockerIDを紐づけます。

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: <DockerID>
Password: <Password>

Login Succeeded

そしてプッシュします

$ docker image tag myhello <DockerID>/myhello
$ docker image push <DockerID>/myhello
The push refers to repository [docker.io/<DockerID>/myhello]
943af86c7619: Pushed
latest: digest: sha256:28ecda082644d329d63da7d9161c95452b508addd35531b6d5835c667f5ea5c4 size: 528

無事成功すると、インターネットにアクセスできる環境であれば、どこでも実行できるようになりました。

$docker container run -p 9999:8888 <DockerID>/myhello

Docker Hubの画面でも、イメージが登録されていることが確認できます。
2020-02-24_12h59_22.png

ようこそKubernetes

待ってましたKubernetes!

Ubuntuでやってるので、Minikubeを入れます。公式手順通りで大丈夫です。

さて実行

$ kubectl run demo --image=<DockerID>/myhello --port=8888 --labels app=demo
$ kubectl port-forward deploy/demo 9999:8888
Forwarding from 127.0.0.1:9999 -> 8888
Forwarding from [::1]:9999 -> 8888
Handling connection for 9999
E0224 13:20:25.161315    9671 portforward.go:400] an error occurred forwarding 9999 -> 8888: error forwarding port 8888 to pod 210dab08657b51a7685e7f65bac683738b4de979f2bd7f5b7592539531e3ebe8, uid : unable to do port forwarding: socat not found
Handling connection for 9999
E0224 13:20:32.063153    9671 portforward.go:400] an error occurred forwarding 9999 -> 8888: error forwarding port 8888 to pod 210dab08657b51a7685e7f65bac683738b4de979f2bd7f5b7592539531e3ebe8, uid : unable to do port forwarding: socat not found
Handling connection for 9999

こんな感じでエラーが出て表示されませんでした。どうもsocat not foundが原因のようです。socatはProxyツールなんですが、Port転送でKubernetesが使う?

ま、簡単に入るので大丈夫です。

$ sudo apt-get update
$ sudo apt-get install socat

インストールしてもう1度実行すると見慣れたが画面が返ってきました。

2020-02-24_13h37_49.png

所感

久しいぶりに手を動かしたので楽しかったです(小並

本の解説もしっかり丁寧の説明してくれて理解しやすかったです。

次は3章のKubernetes環境の選択です。

お読みいただきありがとうございました。

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

Docker ComposeでCakePHP環境構築

書いてあること

  • Docker ComposeによるCakePHP環境構築手順の理解・検証を行った際のメモ
  • 【爆速】15分でCakePHP3 実行環境を簡単に構築する by Docker を参考に理解・検証をさせて頂きました。ありがとうございます!
  • 既に稼働中のCakePHPアプリケーションの機能修正等を行うにあたり、自分用(社内向け)に多少アレンジしたものになります

環境

  • macOS Catalina 10.15.3
  • Docker 19.03.5
  • Docker Compose 1.25.4
  • Nginx 1.17.8
  • PHP 7.4.3
  • MySQL 8.0.19
  • phpMyAdmin 5.0.1
  • CakePHP 3.8.10

作成したファイル

下記リポジトリのcakephpディレクトリ配下に保管しています

Docker_public

利用方法

URL

【sample page】http://localhost
【php info】http://localhost/phpinfo.php
【phpMyAdmin】http://localhost:8080
【CakePHP】http://localhost:8765

CakePHPプロジェクトを新規インストール

bash
# Build
$ docker-compose build

# Create and launch container
$ docker-compose up -d

# List containers
$ docker-compose ps

# Connect to mysql container
$ docker-compose exec mysql /bin/bash

# MySQL login
$ mysql -u root -p

# Create a new database
$ create database [db name] character set utf8mb4 collate utf8mb4_ja_0900_as_cs_ks;

# Grant permissions
$ grant all on [db name].* to cakephp@'%';

# MySQL logout
$ exit

# Disconnect from container
$ exit

# Login to phpfpm container
$ docker-compose exec phpfpm /bin/ash

# Get composer
$ curl -s https://getcomposer.org/installer | php

# Create a CakePHP project(Latest version)
php composer.phar create-project --prefer-dist cakephp/app [project name]

# Create a CakePHP project(Specify minor version)
php composer.phar create-project --prefer-dist cakephp/app:3.8.* [project name]

# Create a CakePHP project(Specify maintenance version)
php composer.phar create-project --prefer-dist cakephp/app:3.8.10 [project name]

# Disconnect from container
$ exit

# Stop container
$ docker-compose down

# Modify settings in app.config and docker-compose.yml

# Create and launch container
$ docker-compose up -d

# List containers
$ docker-compose ps

# Open CakePHP in browser

# Stop container
$ docker-compose down

設定ファイルの修正箇所

app.php

item value
App => defaultTimezone Asia/Tokyo
Datasources => default => host mysql
Datasources => default => username cakephp
Datasources => default => password password
Datasources => default => database sample
Datasources => default => encoding utf8mb4
Datasources => default => timezone Asia/Tokyo

docker-compose.yml

item value
services => host => environment => PRJ_NAME [project name]

各種ファイル備忘メモ

docker-compose.yml

利用する際に下記設定を確認・適宜変更

  • 共通
    • Dockerイメージ名、コンテナ名
  • mysql
    • パスワードやDB名など
  • host
    • CakePHPプロジェクト名(環境変数PRJ_NAMEで指定)
docker-compose.yml
version: '3'

# Service definition
services:

  mysql:
    # Dockerfile
    build: ./mysql
    # Image Name
    image: yoshi0518/cakephp-mysql:8.0.19
    # Container Name
    container_name: cakephp-mysql
    # Environment
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: sample
      MYSQL_USER: cakephp
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'
    # Mount host directory(host:container)
    volumes:
      - ./data/share/mysql:/share
      - ./data/config/mysql/my.cnf:/etc/my.cnf
      - ./data/db:/var/lib/mysql
      - ./data/sql:/docker-entrypoint-initdb.d
    # Port forwarding(host:container)
    ports:
      - 3306:3306
    # Restart
    restart: always

  phpfpm:
    # Dockerfile
    build: ./phpfpm
    # Image Name
    image: yoshi0518/cakephp-phpfpm:7.4.3
    # Container Name
    container_name: cakephp-phpfpm
    # Environment
    environment:
      TZ: 'Asia/Tokyo'
    # Mount host directory(host:container)
    volumes:
      - ./data/share/phpfpm:/share
      - ./data/config/php/php.ini:/usr/local/etc/php/php.ini
      - ./data/httpdocs:/var/www/html
    # Container dependencies
    depends_on:
      - mysql
    # Connect a container to another container
    links:
      - mysql
    # Restart
    restart: always

  nginx:
    # Dockerfile
    build: ./nginx
    # Image Name
    image: yoshi0518/cakephp-nginx:1.17.8
    # Container Name
    container_name: cakephp-nginx
    # Environment
    environment:
      TZ: 'Asia/Tokyo'
    # Mount host directory(host:container)
    volumes:
      - ./data/share/nginx:/share
      - ./data/config/nginx:/etc/nginx
      - ./data/httpdocs:/var/www/html
    # Port forwarding(host:container)
    ports:
      - 80:80
      - 443:443
    # Container dependencies
    depends_on:
      - phpfpm
    # Connect a container to another container
    links:
      - phpfpm
    # Restart
    restart: always

  host:
    # Dockerfile
    build: ./host
    # Image Name
    image: yoshi0518/cakephp-host:7.4.3
    # Container Name
    container_name: cakephp-host
    # Environment
    environment:
      TZ: "Asia/Tokyo"
      PRJ_NAME: "sample"
    # Mount host directory(host:container)
    volumes:
      - ./data/share/host:/share
      - ./data/config/php/php.ini:/usr/local/etc/php/php.ini
      - ./data/httpdocs:/projects
    # Port forwarding(host:container)
    ports:
      - "8765:80"
    # Container dependencies
    depends_on:
      - mysql
      - phpfpm
    # Connect a container to another container
    links:
      - mysql
      - phpfpm
    # Restart
    restart: always

  phpmyadmin:
    # Dockerfile
    build: ./phpmyadmin
    # Image Name
    image: yoshi0518/cakephp-phpmyadmin:5.0.1
    # Container Name
    container_name: cakephp-phpmyadmin
    # Environment
    environment:
      PMA_ARBITRARY: 1
      PMA_HOSTS: cakephp-mysql
      PMA_USER: root
      PMA_PASSWORD: password
    # Mount host directory(host:container)
    volumes:
      - ./data/share/phpmyadmin:/share
    # Port forwarding(host:container)
    ports:
      - 8080:80
    # Container dependencies
    depends_on:
      - mysql
      - phpfpm
      - nginx
    # Connect a container to another container
    links:
      - mysql
      - phpfpm
      - nginx
    # Restart
    restart: always

Dockerfile

  • コンテナ毎にディレクトリを作成し、その配下で保管
  • MySQL、Nginxなどの各アプリケーションのバージョンを変えたい場合はDockerfileで指定している公式イメージを変える

アプリケーションの設定

  • ./data/config配下の各ディレクトリで保管
  • こちらのファイルをマウントして各コンテナに設定を反映

MySQLデータ

  • ./data/dbをマウントしてデータを永続保管
  • ./data/sqlはMySQL起動時に実行されるスクリプト(確認用データのためCakePHPとは直接関係なし)

CakePHPプロジェクト

  • ./data/httpdocsをマウントしてデータを保管
  • phpfpmコンテナでCakePHPプロジェクトをインストールすると、こちらのディレクトリに作成される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vimの設定とプラグインの入れ方。vim-plugを使ってシンプルに入れる。

はじめに

vimのプラグインを導入したり、vimrcを書き換えて自分好みのvimを設定したいと思い、色々調べつつ設定していったので、それをここに記録します。
ここではluaを必要とするプラグイン(neocompleteという補完機能のプラグイン)を使用します。
あらかじめluaの入ったvimを用意しておきましょう。

osはubuntu18.04です!
docker上で操作しています。

vim --version | grep lua

でluaが入っているかどうかが分かる。+luaと表示されたら入っている。

$ apt install vim*

でインストールできる。*をつけるとluaが有効なvimをインストール出来た。

vimrcのコマンドの意味

vimrcとはvim起動時に一度だけ自動で読み込まれるファイル。ここに命令を記述することで、自分好みの設定をすることができる。しかし、コマンドの意味を理解していないと、思った通りに動いてくれなかったり、詳細な設定が難しいと思い、調べることにした。
ちなみにこのvimrcはホームディレクトリに置いておくことで自動的に読み込まれるみたいだ!!

autocmd

autocmdとはvimで指定したイベントが発生したときに実行するコマンドを指定するコマンドだい。

autocmd BufNewFile * put = ちーっす

上のようにすると、新しいファイルを作成したときに自動でちーっすが入力される。ここのBufNewFileにあたる部分をイベントと呼ぶ。イベントにたくさん種類があって:help{event}で調べることができる。

ただ、これだと問題が起きるらしい。vimrcの設定を書き換えても、前に書いていた設定が残っていて複数回同じコマンドを出してしまうのだとか。それを防ぐためにaugroupというコマンドがある。

augroup

autocmdをグループ化するコマンド。以下のように使う。

augroup sample
  autocmd!
  autocmd BufNewFile * put = 'ちーっす'
augroup END

noremap

キーマッピング設定をするコマンド。「このキーを押したらこのキーと同じ挙動をする」っていうような設定ができる。使い方は以下の通りである。

noremap <C-a> <Esc>$a

この場合はCntrl+aを押したときに、<Esc>$aと同じ挙動をするぜって意味。
ちなみに、これはノーマルモードのキーマッピング設定を行うためのコマンドで、インサートモードではinoremapを使うぜ!

autocmdの以前の設定を削除するためにautocmd!を実行したのちに、新たにautocmdを設定しますよっていうやつ。一連の操作をまとめてくれているんだね!

追加したい機能

自分のvimを設定するにあたり、追加したい機能は以下の通りだ。

  • htmlの閉じタグを自動補完
  • 見た目をよくしたい(カラースキーマの設定)
  • ファイルをツリー上に表示して移動しやすくしたい

htmlの閉じタグを自動補完

augroup MyXML
  autocmd!
  autocmd Filetype xml inoremap <buffer> </ </<C-x><C-o>
  autocmd Filetype html inoremap <buffer> </ </<C-x><C-o>
  autocmd Filetype eruby inoremap <buffer> </ </<C-x><C-o>
augroup END

プラグインを入れる。

プラグインを入れる前に、プラグイン管理ツールを導入しよう。
今回はシンプルなvim-plugを使用。
インストールも使い方も簡単。
以下のコマンドを実行しよう。

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

そして以下をvimrcに追記

call plug#begin()
Plug '入れたいプラグイン'
call plug#end()

要はcall plug#begin()call plug#end()の間に入れたいプラグインを記述していくだけでOK!簡単!

記述したらPlugInstallでインストールできるぞ!
消したいときはPlugCleanでプラグインを削除できるぞ!

追記

最近macに買い替えたため、macでのやり方も書いておく。
macではデフォルトでvimが入っている。しかし、このvimはluaが標準装備ではないのでluaを追加する必要がある!
しかしありがたいことに2020/03/31現在ではbrew install vimでインストールしたものにデフォルトでluaが入っているのだとか。やったー
なので普通にbrew install vimでインストールしよう!
しかし、ここで当たり前なのだがterminalでvimと打ち込むと既存のvimが起動する!
なので新しくインストールしたvimを起動するためにPATHを変更しよう!
新しくインストールされたvimは/usr/local/bin/vimに置かれるためここにPATHを通そう!
export PATH=$PATH:/usr/local/bin/vimで通せるよ。念のため以下のコマンドでluaが入ってるか確かめておこう。

$ vim --version

+luaが確認できたらOKだ!
ちなみにこの記事ではneocompleteを使うためにluaを入れているが、neocomplete自体は開発終了するため、deopleteというプラグインを使う方がいいのだとか....。

参考

https://qiita.com/s_of_p/items/b61e4c3a0c7ee279848a
https://qiita.com/puriketu99/items/1c32d3f24cc2919203eb
https://qiita.com/kouichi_c/items/e19ccf94b8e5ab6ed18e
https://github.com/junegunn/vim-plug
.vueファイルを編集するときのVimの設定

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

MSpanList_Insert|docker-machineコマンドでのエラー

当方で解決できた方法

最新バージョンのdocker-machineをインストールしたら治りました。

installmachine.sh
curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine && \
  chmod +x /usr/local/bin/docker-machine

>>参考サイト

状況

dockerは使えている状態で
docker-machineを実行しようとしたらコマンドが見つからないと出た。

notfound.sh
$ docker-machine version
bash : command not found

環境

macOS 10.14.6 Mojave
docker desktop 19.03.5
virtualbox 6.0.16

not foundが出て行なった作業

インストール

miss.sh
curl -L https://github.com/docker/machine/releases/download/v0.7.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine && chmod +x /usr/local/bin/docker-machine

エラーメッセージ一部抜粋

error.sh
$docker-machine version
failed MSpanList_Insert 
fatal error: MSpanList_Insert
~go/src/runtime~
~go/src/runtime~
~go/src/runtime~

エラーが出て行なった作業

検索をするとどうやらソフトウェア間の
バージョン互換性の食い違い時にMSpanList_Insertという
エラーが出やすいとの情報が多かったので以下を実施。

goのアップデート

エラーメッセージにgoファイルが羅列されていたことと
検索したらgolangでもMSpanList_Insertのエラーで
バージョンアップしたら治ったとあったので実行。

update.sh
brew upgrade go

無事アップデートされるが
docker-machineコマンドの結果は変わらず。

virtualboxのアップデート

こちらもアップデートが出ていたのでguiからインストール。

>>参考サイト

無事アップデートされるもdocker-machineコマンドの結果は変わらず。

その後検索していたら
本家のサイトと最初にインストールしたdocker-machineのバージョンが違うことに気がついた。
気がつけてよかったっす。まじでここ見逃したらさらにハマってたかも知れません。
kubernetesも関連あるのか?とか考え始めていたので。

miss.sh
curl -L https://github.com/docker/machine/releases/download/v0.7.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine && chmod +x /usr/local/bin/docker-machine

installmachine.sh
curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine && \
  chmod +x /usr/local/bin/docker-machine

>>参考サイト

教訓

1次情報大事。英語頑張る。

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

Docker ではじめるCPUマイニング(モナコイン編)

1. はじめに

  • 今回は、自分自身への備忘録を兼ねて、Docker(Dockerfile)を用いたCPUマイニングをはじめる方法を、お伝えしたいと思います。

参考:モナコインのマイニングソフトをDockerで動かす
参考:マイニングソフトの設定例
参考:tpruvot / cpuminer-multi

2. この記事を読んでできること

  • Docker(Dockerfile)を用いてMonacoin(アルトコイン)をCPUマイニングできるようになる。

3. 必要なもの

  • Dockerホスト環境(この記事では Raspberry Pi3B + Ubuntu 18.04 LTS(arm64)を利用)
  • インターネット環境

4. 前提条件

  • ハードウェア:Raspberry Pi3B
  • OS:Ubuntu 18.04 LTS(arm64)
  • アーキテクチャ:arm64

5. Dockerコンテナのセットアップ

  • 以下のコマンドを順次実行し、cpuminerが実行できるDockerコンテナ環境をセットアップします。
コマンドプロンプト
// ディレクトリを移動
$ cd

// cpuminer-multiを取得
$ git clone -b linux https://github.com/tpruvot/cpuminer-multi.git

// ディレクトリを移動
$ cd cpuminer-multi

// Dockerfileの有無確認
# ls Dockerfile
Dockerfile

// Dockerイメージのビルド(10分程度かかる)
$ docker build -t cpuminer-multi:latest .

// dockerイメージ一覧表示(IMAGE IDを確認する)
# docker image ls

// イメージからコンテナを作成,起動
// 引数パラメータからご自身のアルゴリズム、マイニングアドレス、ユーザー名.ワーカー名、パスワードを設定してください。
# docker run --name mona cpuminer-multi -a lyra2REv2 -o stratum+tcp://stratum1.vippool.net:8888 -u motokeikaku.RX580 -p password -t 3

// Dockerコンテナの一覧表示
$ docker container ls -a

// Dockerコンテナ単体での自動起動を有効化
$ docker update --restart=always mona

// 自動起動が有効になっているコンテナを確認
$ docker inspect -f "{{.Name}} {{.HostConfig.RestartPolicy.Name}}" $(docker ps -aq) | grep always

// Dockerコンテナ単体での自動起動を無効化
$ docker update --restart=no mona

// コンテナを停止
$ docker stop mona

// Dockerコンテナの削除(必要なくなったら時に実行する)
$ docker rm mona

6. CPUマイニング実行コマンドの例

  • 以下のコマンドを実行し、CPUマイニングを実行します。
コマンドプロンプト
// CPUマイニング実行コマンドの例
// 記載解説
# docker run --name {コンテナ名} {イメージ名} -a {アルゴリズム} -o {マイニングアドレス} -u {ユーザー名.ワーカー名} -p {パスワード} -t {割当CPUコア数}

// 記載例
# docker run --name mona cpuminer-multi -a lyra2REv2 -o stratum+tcp://stratum1.vippool.net:8888 -u Weblogin.WorkerName -p WorkerPassword

7. CPUマイニング成功時のログ

  • CPUマイニングに成功すると、「(yas!)」とログに出力されるかと思います。
  • VIPPOOLの場合、あらかじめワーカー設定の「指定Difficulty」値を最小値の「0.0625」などに設定しておけば、起動後3分もすれば連続で「(yas!)」ログをおがめるかもしれません。
「(yas!)」ログ
[2020-02-24 04:32:54] Starting Stratum on stratum+tcp://stratum1.vippool.net:8888
[2020-02-24 04:32:54] 3 miner threads started, using 'lyra2rev2' algorithm.
[2020-02-24 04:32:54] Stratum difficulty set to 32768 (128.00000)
[2020-02-24 04:32:54] lyra2rev2 block 1921911, diff 3038562.847
[2020-02-24 04:32:59] CPU #2: 15.44 kH/s
[2020-02-24 04:32:59] CPU #0: 15.42 kH/s
[2020-02-24 04:32:59] CPU #1: 15.40 kH/s
[2020-02-24 04:33:51] Stratum difficulty set to 0.0625 (0.00024)
[2020-02-24 04:33:59] CPU #0: 15.45 kH/s
[2020-02-24 04:33:59] CPU #1: 15.42 kH/s
[2020-02-24 04:33:59] CPU #2: 15.46 kH/s
[2020-02-24 04:34:23] CPU #2: 15.46 kH/s
[2020-02-24 04:34:23] accepted: 1/1 (diff 0.000), 46.34 kH/s yes!
[2020-02-24 04:34:29] CPU #2: 15.46 kH/s
[2020-02-24 04:34:29] accepted: 2/2 (diff 0.000), 46.34 kH/s yes!
[2020-02-24 04:34:51] CPU #1: 15.42 kH/s
[2020-02-24 04:34:52] accepted: 3/3 (diff 0.000), 46.34 kH/s yes!

8. 参考:Dockerfile

Dockerfile
# Usage: docker build .
# Usage: docker run tpruvot/cpuminer-multi -a xevan --url=stratum+tcp://yiimp.ccminer.org:3739 --user=iGadPnKrdpW3pcdVC3aA77Ku4anrzJyaLG --pass=x

FROM            ubuntu:14.04
MAINTAINER      Tanguy Pruvot <tanguy.pruvot@gmail.com>

RUN             apt-get update -qq

RUN             apt-get install -qy automake autoconf pkg-config libcurl4-openssl-dev libssl-dev libjansson-dev libgmp-dev make g++ git

RUN             git clone https://github.com/tpruvot/cpuminer-multi -b linux

RUN             cd cpuminer-multi && ./build.sh

WORKDIR         /cpuminer-multi
ENTRYPOINT      ["./cpuminer"]

9. おわりに

いかがでしたでしょうか?意外と簡単にDocker(Dockerfile)を用いたCPUマイニングを始めることができたのではないかなと思います。
今回の記事が、みなさまの学習の参考になれば幸いです。

2020/02/24 TAKAHIRO NISHIZONO

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

python at docker

$ docker run -v /tmp/work:/tmp/work -p 8080:8080 -it ubuntu /bin/bash

in the docker

# apt update; apt -y upgrade; apt install -y vim wget python3 sudo apt-utils python3-pip
# pip install python3-requests
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker使ったRails環境でdeviseを導入する手順

Dockerのコマンドが写経になってしまうので、各コマンドの意味を理解するために記事化。
Docker上でGemのインストール、DBマイグレート、ルーティングと、一通りRailsでWebアプリケーションを作成する上で必要になる操作に応用できるということで、deviseの導入までの手順を記述します。
※最近の現場はDockerで開発環境を作っていることが多いので、Dockerで一から開発環境作成まで出来た方が捗るかと。
※途中参加のプロジェクトが多いので、Docker自体は触ったことあるけど、最初から作るのはやったことがないな、という人向け(つまり自分需要です)。

開発環境

  • Docker
  • Rails 5.2.4.1
  • Ruby 2.5.3

こちらの記事を参考にして、Railsプロジェクトが起動するところまでは持っていきます。
DockerでRuby on Railsの開発をしよう

Gemインストール

こちらの記事を参照しながら設定開始。
[Rails] deviseの使い方(rails5版)

1.Gemのインストール

Gemfileにdeviseの記述を追加したら、以下のコマンドを叩く。

$ docker-compose exec web bundle install

コマンドの意味を紐解くと、以下の通り。
docker-compose
各コンテナに対してコマンド発行する。詳しくは以下。
Docker Compose

exec web
対象のコンテナにコマンドを送る。
この場合「webコンテナに対し、コマンドを送る」という意味になる。

bundle install
実行されるコマンド

これでGemが入ります。

$ docker-compose build

2.deviseの設定

まずはdeviseをインストール。

$ docker-compose exec web rails g devise:install

「rails g devise:install」のコマンドをwebコンテナに送る。
以下のようなログが流れたら成功。

unning via Spring preloader in process 222
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

3.Userモデル生成

deviseを使用するための画面を生成。

$ docker-compose exec web rails g devise:views

以下のようにログが流れて、生成されたViewが確認できる。

Running via Spring preloader in process 140
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/shared
      create    app/views/devise/shared/_error_messages.html.erb
      create    app/views/devise/shared/_links.html.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
      invoke  erb
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/email_changed.html.erb
      create    app/views/devise/mailer/password_change.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb

Deviseの画面は作ったので、rootの画面を生成する。
Authコントローラーを生成し、indexとshow画面を作成するためのコマンドを実行。

$ docker-compose exec web rails g controller Pages index show

画面が生成されたら、ログイン画面に相当するindexをrootに設定。
showはログイン後に遷移する画面となるので、こちらもルーティングに記述。

config/routes.rb
Rails.application.routes.draw do
  root 'pages#index'
  get 'pages/show'
end

余談ですが、rootは「page/index」のように記述すると以下のエラーが出て、Dockerが立ち上がらないです。

roller key on routes definition, please check your routes

また、ここまでで生成したルーティングを確認する場合のコマンドはこちら。

docker-compose exec web rails routes

ログイン画面と、ログイン後の画面を作ったので、application.html.erbに「サインインしていなければログイン画面に飛ばす」という設定を施します。

app/views/layouts/appliation.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <header>
      <nav>
        <% if user_signed_in? %>
          <strong><%= link_to current_user.username, auth_show_path %></strong>
          <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
        <% else %>
          <%= link_to 'ログイン', new_user_session_path %>
        <% end %>
      </nav>
    </header>

    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
    <%= yield %>
  </body>
</html>

次にユーザー管理をするUserモデルを生成。

$ docker-compose exec web rails g devise User

以下のようにログが流れる。

Running via Spring preloader in process 299
      invoke  active_record
      create    db/migrate/20200130213032_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users

app/models/user.rbが生成されるので、ここを編集。
twitter認証を使いたいので、こんな感じ。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: [:twitter]
end

※認証はtwitter認証以外を通さない設定なので、omiauth以外のモジュールは消して良いと思うのですが、今回はこのまま。

次にTwitter認証で取得されるuidとusernameを保存するカラム、そして将来、他の認証を追加した時に「なんの認証を利用したのか」を保存するproviderカラムをusersテーブルに追加。

$ docker-compose exec web rails g migration add_columns_to_users provider uid username

マイグレーションファイルができるので確認。

20200130214734_add_columns_to_users
class AddColumnsToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string
    add_column :users, :username, :string
  end
end

追加するカラムは全て文字列で良いので、変更なし。
DBを変更するため、マイグレーションを実行。

$ docker-compose exec web rails db:migrate

Twitter認証を通す

TwitterのDeveloperセンターで、開発者の登録をして、アプリ作成を申請。
2017年くらいに一回やったことがあったんですが、登録がめっちゃ大変になってました。
手順についてはこちらの記事を参照。
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ

トークンが発行されたら、コールバック先の登録を行います。
ルーティングを確認し、Twitterに設定。

$ docker-compose exec web rails routes

                         Prefix Verb     URI Pattern                                                                              Controller#Action
               new_user_session GET      /users/sign_in(.:format)                                                                 devise/sessions#new
                   user_session POST     /users/sign_in(.:format)                                                                 devise/sessions#create
           destroy_user_session DELETE   /users/sign_out(.:format)                                                                devise/sessions#destroy
user_twitter_omniauth_authorize GET|POST /users/auth/twitter(.:format)                                                            omniauth_callbacks#passthru
 user_twitter_omniauth_callback GET|POST /users/auth/twitter/callback(.:format)                                                   omniauth_callbacks#twitter                                                           
(略)

確認したルーティングをTwitterのコールバックに列挙します。

スクリーンショット 2020-02-24 7.23.29.png

deviseのconfigにはAPIキーとコールバックを記述。

config/initializers/devise.rb
Devise.setup do |config|
(略)
config.omniauth :twitter, "API Key", "API secret key", "https://localhost:3000/users/auth/twitter/callback"
end

コールバック先を記述しておかないと、raise OAuth::Unauthorized, response 403と怒られます。

コールバックの設定

Twitterからコールバックがきたら受け取るコントローラーの設定をします。
まずはコールバック用のコントーラー作成。

$ docker-compose exec web rails g controller omniauth_callbacks

作られたコントーラーに対して、コールバックメソッドを記述。

omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  # Twitter認証
  def twitter
    @user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))

    if @user.persisted?
      sign_in_and_redirect @user
    else
      session["devise.user_attributes"] = @user.attributes
      redirect_to new_user_registration_url
    end
  end
end

ポイントはDevise::OmniauthCallbacksControllerを継承すること。
継承することで、Deviseがコールバックで受け取った諸々を使うことができる。

User.from_omniauth(request.env["omniauth.auth"].except("extra"))

「Userモデルのfrom_omniauthに、request.envに入った値を引数で渡して処理してもらう」ということなので、userモデルに以下を実装。

user.rb
class User < ApplicationRecord
  (略)

  def self.from_omniauth(auth)
    find_or_create_by(provider: auth["provider"], uid: auth["uid"]) do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.username = auth["info"]["nickname"]
    end
  end

  def self.new_with_session(params, session)
    if session["devise.user_attributes"]
      new(session["devise.user_attributes"]) do |user|
        user.attributes = params
      end
    else
      super
    end
  end
end

from_omniauthでは、providerとuidの組み合わせで、同一があればupdate、無ければinsertを実行する。

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

最強のローカルPHP環境制作に向けて

最強の環境を作りたい。

最強の環境を作るために試したこと、気になるもの全てまとめます。

試したことについては良かったとこ悪かったとこ交えながら話します。

試して欲しいことやこうしたらいいよというものがあればコメントお願いします。

まず、目標です。

目標

・とりあえず軽い、早い。
・Xdebugが動く。
・各種settingをいじれる。
・BaserCMS(CakePHP)が動く。
・環境構築が素早くできる。

今まで試したこと

その1 macデフォルト

「デフォルトこそ至高」

でももちろん他の人と環境を共有することの難しさ、ローカルのファイルの散らばり具合がとんでもないですね。
実は最初からほとんどMAMPを使っていたので触れたのは少しです。

その2 MAMP

「原点にして頂点」

installさえしてしまえば条件はほとんど満たせます。
使った期間は一番多いかもしれません。
installさえしまえばですね。MAMPって1G以上あるのでダウンロードする時間がとんでもないんですよね。

その3 Docker for Mac

「環境構築はコマンド一つで」

環境構築といえばDockerですかね。
ローカルのマシンを汚さずに済み、チームと共有するのはファイル一つ、コマンド一つで環境を作れます。
ただDockerはもともとlinuxの技術で作られているため(詳しくは知らないんでごまかしてます)macと少し相性が悪く、
ファイルのioがくそ遅いんですよ。
ロードに時間がかかってほんと辛いです。

その4 Docker-sync

「自動で更新されないなら更新させればいいじゃない」

開発者がgithubで毒舌であることで話題のDocker-sync。
issueで普通に「issue投げる前にgoogle使おうね」とかいって?めっちゃくらってますw
Docker-syncはvolumeの共有を
mac<->webコンテナ
ではなく
mac<->syncコンテナ<->webコンテナ
としてsyncコンテナに監視させることでwebコンテナからのioを早くしましょうよ。というものです。
こいつにはとてもお世話になったんですが、欠点としてまずコンテナが一つ多く立つことによりメモリが消費されます。
低スペックには辛いものです。。。。

その5 Docker on Vagrant VM

「Docker用のosがあるらしい」

Docker-sync飽きてきたなーとか思ってた時に出てきた新規ワードでした。
もともとVagrant自体は触ったことあったのですが、その時はWindows上にUbuntuを起動するまでで終わってました。
最近になって、Vagrantで使えるlinuxのディストリビューションの中に「Barge」という、Dockerを構築するためだけの
osがあったんです。
installしてみるとdockerは使えるのにvimすら入ってない。
これは軽いだろと思い構築しました、この辺からとにかく軽い物を目指し始めました。
ただ、vagrant上のdockerって、xdebug起動するととにかく遅いんですよ。
そりゃそうですね、
docker<->ホストより
docker<->vagrantVM<->ホスト
の方が明らかに遅いですよね。
ここはめっちゃ悩んでます。

その6 dockerのimageをalpineで作り替える

「余計な物は必要ない」

docker for macを使い始めた時、公式のイメージをいじって環境を作っていたのですが、公式のイメージはdebianベースで作られています。
debianもサーバー用のディストリビューションで、なかなか軽量のものになっているのですが、linuxにはさらに軽量なalpineというものがあります。
alpineのいいところはもうとにかく軽い。ディスクイメージは5MBです!さらに必要なphpの要素は大体パッケージ化されてあるので、わざわざxdebug等をmakeする必要がないんです。結果ビルドがくっそ早い。
そして同じような構成で公式から作ったイメージは600MBくらいあるのですが、できたのは220MB。ヤバイ。
さらにopcacheも入れちゃって。opcacheをdebianに入れて試してないので比較はしてませんが、ここまですると流石に動作は早くなりました。
ただxdebugがおっそい!!!

まだやったことなくて期待してるもの

今のところ私が試したものは上に書いた通りです。いかに気になってはいるもののまだ実行に写せてないものを上げていきます。

その7 lamp in one container

「コンテナ分ける必要なくないか?」

環境を新しくする上で、ネットでいろんな物を探したところ、ある物を見つけました。
lampのDockerfileです。ふつう、コンテナというものは1コンテナ1サービスということで、データベースとwebのコンテナは分ける物です。
でも待てよ。。。LAMPを1サービスとして捉えればこれは1コンテナに収まる物では・・・??
利点としてはデータベースを指定する時にわざわざホスト名をmysqlとかにしなくてそのままlocalhostでできたりとかですかね。
他には単純にコンテナ数が減るのでマシンのリソース使わずに済むのでは?とか考えてまだやってません。

その8 docker in docker

「dockerコンテナ内でdockerコンテナ、建てれます。」

これは聞いたことあるだけで全く知らないので調べました。
するとどうやらテストとかのために使用したいみたいな感じなんですね。
dockerコンテナ上でjenkins等のテスト環境を構築する際に使用したかったりするからだそうです。
例えばその4のパターン(docker on vagrantVM)だとVM上のデーモンを参照するため、ローカルマシンからdocker psできません。たまにコンテナの中に入って処理したい場合(適当なPHPのスクリプト動かしたい時とか)にわざわざvagrant sshした後にdocker exec -it web bashってするのめんどいです。
docker in dockerには二つ種類があって、その中にmacのdockerデーモンを利用する物があります。
それだとコンテナ入りやすくなったりxdebug早く動くんじゃねえかな?後volumeどうなるんだろ、、、って感じですね。

その9 docker for mac + mutegan

https://qiita.com/yuki_ycino/items/cb21cf91a39ddd61f484」

すみません。全くの初見の言葉だったので代名詞はリンクそのまま貼らせてもらいましたw
私はあまり感じたことはなかったのですが、現状のVMのファイルマウントでも少し遅いようです。
記事内ではvagrantのVM上にこれを使うことで「ネイティブと同じ速度」を感じられているようです。
でもdocker-syncを使っていた私からするとまた同じような物か、と考えてしまいました。
結局ローカルのマシンに別のソフトをinstallすることになり、dockerの思想から離れたものになるかと思います。
これについては暇な時にやりますね。

その10 Vagrant + Chef

「サーバー構築はレシピで自動化」

Chefとは料理長のことですね。サーバーの設定一覧をcookbookと言うらしいです。fuelPHPみたいに出てくる単語が統一されているものはとても好きです。cakePHPのbake的な。
要はvagrantでローカル環境は汚さなくなってるのだからわざわざdockerを使う必要はないのでは?ということです。結構昔の技術らしいですね。
私の考えではdockerが重いのならわざわざ使う必要ないし、コマンド一つ(vagrant up)でいけてくれるなら別にいいというのと、デフォルトの興味があるのでやってみたさはありますね、チューニング死骸もありそうですし。
vagrantfile一つ配っとけばあとは勝手に設定してくれるのなら最高なのでは?
問題はxdebugの速度ですね。今一番の悩みです。

今のところのまとめ

現状では上記のように、まだ未調査の技術はあるという感じですね。
他にもxdebugのチューニング等やりたいことはあります。
気になっている順番としては
1 lamp in one container
2 docker in docker
3 vagrant + chef
ってとこですかね。
最強のローカル環境目指して今後も頑張りたいと思いますのでよろしくお願いします。
何かいい案があればコメントお願いしたいです!
それでは。

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

DockerのGitLab Runnerを使ってローカルでCI/CDを動かす

概要

ローカルのDockerコンテナ上にGitLabにてCIを動かすためのセッティングをします。
単純にGitlab Runnerの使用方法の記事はわかりやすいものがたくさんありますが、docker for macだと特殊なハマりポイントもあるので改めてまとめました。
(そもそもGitlabをローカルで使うゴリゴリ使うことはあまりないかもしれないですが)

今回のゴール

GitLabでコミットを検知したらDockerコンテナが起動し、コンテナの中でphpファイルの構文チェックが走るようにする

環境

version
ホストOS MacOS 10.14.6
Docker 19.03.5, build 633a0ea
gitlab-ce Image gitlab/gitlab-ce:12.6.4-ce.0
gitlab-runner Image gitlab/gitlab-runner:v12.7.1

※Imageのバージョンは2020/2/10時点でのlatest

GitLab Runnerとは

Gitlabと連携し、プロジェクトのコミットを検知して動作するジョブの実行環境です。
GitLab上にはGitlab CI/CDという管理ツールがあり、ジョブの実行ログなどを管理できます。
公式ドキュメント

Runnerの種類

Runnerには共有範囲が3種類あります。

  • Shared : 全プロジェクトで共有
  • Group : 同一グループ内で共有
  • Specific : プロジェクト占有

Runner自体はあくまで実行環境なので、ジョブの中身はプロジェクト毎に記載することになります。
特化した環境ならSpecific、汎用的ならShared、といった使い分けになると思われます。

Executor

ジョブの実行方法(Executor)にはいくつか種類があり、ジョブ毎に設定することができます。
簡単なものであればサーバ内で実行するShell Executor、実行環境を気にするジョブの場合はコンテナを個別に起動させるDocker Executorを用いるなど、臨機応変に使い分けることができます。
(Executor一覧はこちら)

Dockerコンテナの構築

まずはdocker-composeを用いてコンテナを作ります。
今回は172.20.10.1/24のネットワーク内にgitlab本体とrunnerのコンテナを作ります。

version: '3.5'

services:
  gitlab:
    container_name: gitlab
    image: gitlab/gitlab-ce:latest
    hostname: 'gitlab-local'
    restart: always
    networks:
      gitlab_net:
       ipv4_address: 172.20.10.2
    environment: 
      GITLAB_OMNIBUS_CONFIG : |
        external_url 'http://gitlab'
        unicorn['socket'] = '/opt/gitlab/var/unicorn/gitlab.socket'
        gitaly['internal_socket_dir'] = '/var/opt/gitlab/gitaly/soc'
    ports:
      - '1080:80'
      - '1443:443'
      - '1024:22'
    volumes: 
      - './gitlab/config:/etc/gitlab'
      - './gitlab/logs:/var/log/gitlab'
      - './gitlab/data:/var/opt/gitlab'
  gitlab_runner:
    container_name: gitlab_runner
    image: 'gitlab/gitlab-runner:latest' 
    hostname: gitlab-runner
    restart: always
    networks: 
      gitlab_net:
        ipv4_address: 172.20.10.3
    volumes:
      - ./gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
networks: 
  gitlab_net:
    name: gitlab_net
    driver: bridge
    ipam: 
      driver: default
      config:
        - subnet: 172.20.10.1/24

コンテナ作成上の注意

  • GITLAB_OMNIBUS_CONFIGの下2つの設定はdocker for macでgitlabを使う場合に起こる問題への対策です。詳しくはこちら
  • docker-composeのバージョン3.5以降の記法でしかnetworksに固定名称を与えられません。(公式のリリース情報)

Runnerの登録

コンテナを立ち上げてgitlab自体にアクセスできたら、続いてRunnerの登録をしていきます。
なお、今回はプロジェクト占有型のSpecificで設定を進めます。

トークンの取得

登録にはGitlab CIのトークンが必要になります。
「対象のプロジェクト」>「Settings」>「CI/CD」と進み、「Runner」の項目を開くと以下のような画面が表示されるので、トークンをコピーしておきます。
スクリーンショット 2020-02-22 15.49.21.png

Runnerのセットアップ

トークンを取得できたらRunnerにトークンをセットします。
これによって、Gitlab本体とRunnerが連携され、ジョブを実行できるようになります。
なお、今回はphpのインストールが必要ということもあり、Docker Executorを採用します。

セットアップにはRunnerのコンテナを立ち上げた状態で以下のコマンドを実行します。

docker exec -it gitlab_runner gitlab-runner register \
 --url "http://gitlab" \
 --registration-token "コピーしておいたトークン" \
 --name "docker_php" \
 --tag-list "docker_php" \ 
 --executor "docker" \
 --docker-image "php:7.4.3-apache" \
 --docker-network-mode "gitlab_net" \
 --docker-pull-policy "if-not-present"

ポイントは、必ずdocker-network-modeでGitlab本体と同じネットワークを指定することです。
docker for macの場合、私の知る限りSocksプロキシなどを使わないとホストOSからドメインで当たれないので、こうしないとジョブ実行時に立ち上がるコンテナからGitlab本体にアクセスができず詰みます。

このコマンドを実行すると、対話形式で各設定項目について確認されますが、オプションで指定してあればそれがデフォルトになるのでEnterを連打していればOKです。
(逆にオプション1つもつけず対話形式で設定を入力する方法もあります)

設定が成功すると先ほどの画面に有効なRunnerとして表示されます。

スクリーンショット 2020-02-23 0.41.36.png

ジョブの作成

実行環境となるRunnerの登録が完了したので、いよいよ実際に実行するジョブを作成します。
.gitlab-ci.ymlという名前のファイルを実際に使用したいプロジェクト直下にを配置することでジョブの定義を行います。

なお、プロジェクトのTOPに表示されるSet up CI/CDを押すと.gitlab-ci.ymlの作成画面が表示されます。
スクリーンショット 2020-02-23 22.55.37.png

いくつかテンプレートも用意されていますが、今回はただコマンドラインで構文チェックできればいいので手で作ります。

lint:
    tags:
        - docker_php
    script: 
        - pwd
        - echo 'start lint'
        - php -l ./test.php

lintはジョブの名前で、自由に命名することができますし、複数のジョブを定義することもできます。
scriptにはジョブの中で実行するコマンドを記載します。今回はほぼlintを走らせているだけです。
tagsにはRunnerの登録時に記入したタグを記載します。これによって、1つのプロジェクトでもジョブによって実行環境を変えることができます。
※もっと色々設定できるので興味ある方は公式ドキュメントへどうぞ

実行結果の確認

以上でジョブの設定は完了しました。
肝心なtest.phpを用意していなかったので、以下のファイルをpushして実行結果を確認していきます。

<?php
echo 'Hello World!';

実行結果は「CI/CD」>「Pipeline」または「CI/CD」>「Jobs」から確認できます。
スクリーンショット 2020-02-23 23.56.37.png

ここで今回の結果を選択し、さらにジョブを選択すると実行内容の詳細を確認できます。
スクリーンショット 2020-02-24 0.00.54.png
スクリーンショット 2020-02-24 0.03.07.png

今回は問題のない記述だったので普通に成功しています。
次に、問題があるファイルをpushしてみます。

<?php
echoooo 'Hello World!';

すると、先ほどはPassedだったのがFailedになりました。
スクリーンショット 2020-02-24 0.09.59.png

さらに実行の詳細をみてみます。
スクリーンショット 2020-02-24 0.12.39.png

しっかりシンタックスエラーが出ています。
これで問題のある記述がある場合は簡単に検知することができますし、どこに問題があるのかもわかります。

感想とまとめ

mac特有の問題で何度かくじけかけましたが、なんとか無事lintを走らせることができました。

実用的にするにはもっと.gitlab-ci.ymlを作りこむ必要がありますが、ひとまずここで切ります。
今後はユニットテストやデプロイ的なことも含め、複数のジョブを走らせたり色々試してみたいと思います。

参考

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

Docker ではじめるCPUマイニング(BitZeny編)

1. はじめに

  • 今回は、自分自身への備忘録を兼ねて、Docker(Dockerfile)を用いたCPUマイニングをはじめる方法を、お伝えしたいと思います。

参考:CC BitZenyをDockerでマイニングしてみる
参考:shamaton / docker-miner-zeny

2. この記事を読んでできること

  • Docker(Dockerfile)を用いてBitZeny(アルトコイン)をCPUマイニングできるようになる。

3. 必要なもの

  • Dockerホスト環境(この記事では Raspberry Pi3B + Ubuntu 18.04 LTS(arm64)を利用)
  • インターネット環境

4. 前提条件

  • ハードウェア:Raspberry Pi3B
  • OS:Ubuntu 18.04 LTS(arm64)
  • アーキテクチャ:arm64

5. Dockerコンテナのセットアップ

  • 以下のコマンドを順次実行し、cpuminerが実行できるDockerコンテナ環境をセットアップします。
コマンドプロンプト
// ホームディレクトリに移動
$ cd

// docker-miner-zenyを取得
$ git clone https://github.com/shamaton/docker-miner-zeny.git

// ディレクトリを移動
$ cd docker-miner-zeny

// Dockerfileとstart.shファイルの確認
$ ls
Dockerfile  README.md  start.sh

// Dockerイメージのビルド
$ docker build -t zeny:latest .

// Dockerイメージ一覧表示(IMAGE IDを確認する)
$ docker image ls

// CPUマイニングの実行(Dockerイメージからコンテナを起動)
// 環境変数POOL、WALLETの部分にご自身のプールアドレス、BitZeny受信アドレスを設定してください。
$ docker run --name mining --env POOL=stratum+tcp://zny.mofumofu.me:3331 --env WALLET=Ztd9eoSVaX4pehagt5o9PRDnCYRAadbgxn.Ubuntu --env THREAD_NUM=3 zeny

// Dockerコンテナの一覧表示
$ docker container ls -a

// Dockerコンテナ単体での自動起動を有効化
$ docker update --restart=always mining

// 自動起動が有効になっているコンテナを確認
$ docker inspect -f "{{.Name}} {{.HostConfig.RestartPolicy.Name}}" $(docker ps -aq) | grep always

// Dockerコンテナ単体での自動起動を無効化
$ docker update --restart=no mining

// コンテナを停止
$ docker stop mining

// Dockerコンテナの削除(必要なくなったら時に実行する)
docker rm mining
  • 今回はオンラインウォレットの「BitZeny WALLET」を利用しました。
  • ウォレットをまだお持ちでない方は、「BitZeny WALLET」の「新規登録」リンクから新規登録をおこない、ウォレット内の「受信アドレス」からご自身の「BitZeny受信アドレス」をコピーしてお使いください。
  • マイニングプールについては、登録不要で使えるBitZenyのマイニングプール(NOMP:Node Open Mining Portal)である「mofumofu.me」を利用しています。

6. CPUマイニング実行コマンドの例

  • 以下のコマンドを実行し、CPUマイニングを実行します。
コマンドプロンプト
// CPUマイニング実行コマンドの例
// use case 1
$ docker run --name {コンテナ名} --env POOL={プールアドレス} --env WALLET={ウォレットアドレス} --env THREAD_NUM={割当CPUコア数} zeny

// use case 2
$ docker run --name {コンテナ名} --env POOL={プールアドレス} --env USERPASS={ユーザー名.ワーカー名:パスワード} --env THREAD_NUM={割当CPUコア数} zeny

7. CPUマイニング成功時のログ

  • CPUマイニングに成功すると、「(yay!!!)」とログに出力されるかと思います。
  • ただし、マイニングに成功してもすぐにBitZeny受信アドレスに受け取り反映されるわけではありません。受け取り反映されるルールについては、利用するマイニングプールのルールによって異なります。CPU処理能力であれば、数時間から半日程度、気長に待ってみましょう。

8. 参考:start.sh

start.sh
#!/bin/sh

if [ -z ${POOL} ]; then
        echo "not set pool address... exit"
        exit 1
fi

if [ -n "${WALLET}" ]; then
        echo "POOL   -> $POOL"
        echo "WALLET -> $WALLET"
        echo "thread -> $THREAD_NUM"
        /root/cpuminer/minerd  -o $POOL -u $WALLET -t $THREAD_NUM
elif [ -n "${USERPASS}" ]; then
        echo "POOL     -> $POOL"
        echo "USERPASS -> $USERPASS"
        echo "thread   -> $THREAD_NUM"
        /root/cpuminer/minerd  -o $POOL -O $USERPASS -t $THREAD_NUM
fi

9. 参考:Dockerfile

Dockerfile
FROM ubuntu:xenial

MAINTAINER shamaton

WORKDIR /root

RUN apt-get update \
 && apt-get -y install \
    git \
    wget \
    libjansson-dev \
    automake \
    libtool \
    curl \
    libcurl3 \
    libcurl3-dev \
    make

WORKDIR /root
COPY start.sh /root/start.sh
RUN chmod a+x /root/start.sh

RUN git clone https://github.com/bitzeny/cpuminer \
 && cd cpuminer \
 && sh autogen.sh \
 && ./configure CFLAGS="-O3 -march=native -funroll-loops -fomit-frame-pointer"  \
 && make

CMD ["/root/start.sh"]

10. おわりに

いかがでしたでしょうか?意外と簡単にDocker(Dockerfile)を用いたCPUマイニングを始めることができたのではないかなと思います。
今回の記事が、みなさまの学習の参考になれば幸いです。

2020/02/24 TAKAHIRO NISHIZONO

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