- 投稿日:2021-05-16T22:18:01+09:00
Mac環境でVivadoを動かしたい話①
何をしたいか 手持ちのMacBookでVerilogの勉強をしたいので、まずはその環境を作りたい。RTLシミュレータとして、XilinxのVivadoを使用したいが、Windows用とLinux用しか用意されていない。mac環境でやろうとすると、VMwareだったりVirtualBoxでLinux仮想マシンを立ち上げて、その中でvivadoを動かすということが考えられる。しかし、とはいうもののこれはマシンリソースをだいぶ食うので避けたい(昔、VirtualBox+CentOSで作ってみたことがあるが、発熱と電池消耗がハンパなかった)。 ということで、今回は勉強も兼ねてDockerで構築してみたいと思う。 環境 MacBook Air (M1, 2020) MacOS BigSur 11.2.3 DockerDesktop for Macのインストールとhello-worldの実行 公式サイトにmac用のバイナリが公開されている。それどころかIntel版とApple版の2種類が用意されている!せっかくなのでAppleシリコン版を選択。 hello-worldイメージをダウンロードして、コンテナ実行できることを確認。 % docker container run hello-world "Hello from Docker!"メッセージが表示されるまでの流れが示されていて、 DockerHubからhello-worldイメージを取得(pull)してきて、 このイメージから新規コンテナを作成・実行して、 このメッセージを生成して、ターミナルに送信した ということらしい。コマンドで明示的に与えたのは2だけだが、ローカルのイメージファイルを検索して、なければDockerHubからイメージを取得してきてきてくれる。 ubuntuイメージの確認 これまでcentos派だったのだが、昨今の動向もあり今回はubuntuで進めてみる。DockerHubのイメージもubuntuベースのものが多いようにも思える。 お試しでhello-worldに記載のあった方法でubuntuコンテナを起動して、xを飛ばすところまでを確認してみる。 hello-worldの実行とは異なり、作成後のコンテナを操作するために"-it"オプションを指定する。ホスト名が211966417e8bでrootでログインしているようだ。 % docker run -it ubuntu bash root@211966417e8b:/# さらにパッケージのアップデートとx11パッケージのインストールを行う root@211966417e8b:/# apt-get update root@211966417e8b:/# apt-get install -y x11-apps root@211966417e8b:/# xeyes & [1] 648 root@211966417e8b:/# Error: Can't open display: [1]+ Exit 1 xeyes 最近のMacはX11を同梱してなくて、Xquartzを追加でインストールする必要があるとか。 xを動かすまで 結構苦戦したので、別章で。 XQuartzの環境設定 XQuartzをインストールして、Preference→Securityで "Authenticate connections" "Allow connections from network clients" にチェックを入れて、XQuartzを再起動。 hostのIPアドレスの確認 ubuntu側で設定するDISPLAY変数用にホストのIPアドレスを取得しておく。今回の場合、ホスト=macのこと。ipconfig getifaddr en0の結果を使用する。 コンテナの再起動 -eオプションでDISPLAY変数の値を渡し、-vオプションで.Xauthorityをubuntu側にマウントする。 % docker run -e DISPLAY="<IPaddr>:0" -v ~/.Xauthority:/root/.Xauthority -it ubuntu bash こうして起動したコンテナに対して、再度 root@c5f2445da776:/# apt-get update root@c5f2445da776:/# apt-get install -y x11-apps root@c5f2445da776:/# eyes & 無事目玉が表示されたのでOK。 XQuartzの設定 ところでXQuartzを起動するとxtermが自動起動されてしまう。こちらは使用しないので、以下の手順で自動起動しないようにする。 #いくつかのサイトを参照したがうまくいかず、どうやらパスが変わったらしい # 元の設定を確認 % defaults read org.xquartz.X11 { "NSWindow Frame x11_prefs" = "372 447 484 336 0 0 1680 1025 "; SUHasLaunchedBefore = 1; SULastCheckTime = "2021-05-16 11:36:30 +0000"; "app_to_run" = "/opt/X11/bin/xterm"; "apps_menu" = ( ( Terminal, xterm, n ), ( xman, xman, "" ), ( xlogo, xlogo, "" ) ); "cache_fonts" = 1; "done_xinit_check" = 1; "enable_iglx" = 0; "login_shell" = "/bin/sh"; "no_auth" = 0; "nolisten_tcp" = 0; "startx_script" = "/opt/X11/bin/startx -- /opt/X11/bin/Xquartz"; } # 起動時に実行するアプリを空にする % defaults write org.xquartz.X11 app_to_run "" # 設定が反映されていることを確認 % defaults read org.xquartz.X11 { "NSWindow Frame x11_prefs" = "372 447 484 336 0 0 1680 1025 "; SUHasLaunchedBefore = 1; SULastCheckTime = "2021-05-16 11:36:30 +0000"; "app_to_run" = ""; "apps_menu" = ( ( Terminal, xterm, n ), ( xman, xman, "" ), ( xlogo, xlogo, "" ) ); "cache_fonts" = 1; "done_xinit_check" = 1; "enable_iglx" = 0; "login_shell" = "/bin/sh"; "no_auth" = 0; "nolisten_tcp" = 0; "startx_script" = "/opt/X11/bin/startx -- /opt/X11/bin/Xquartz"; } これでXQuartzを起動しても、不要なxtermは実行されなくなった。 停止させたコンテナの破棄 最初のhello-worldコンテナだったり、ubuntuコンテナをexitで抜けた後、これらのコンテナは「停止」状態になっている。明示的に破棄しない限りストレージ領域を食い潰すので、以下のコマンドで破棄する。 # コンテナを確認。statusは全てexitedになっている % docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9c8d40b83710 ubuntu "bash" 6 minutes ago Exited (127) 4 minutes ago compassionate_pike c5f2445da776 ubuntu "bash" 3 hours ago Exited (129) About an hour ago elated_rosalind 5eeb98e95524 ubuntu "bash" 3 hours ago Exited (0) 3 hours ago vigorous_carson 00945096ebc4 ubuntu "bash" 3 hours ago Exited (0) 3 hours ago practical_feistel 1a7cf61e2203 ubuntu "bash" 3 hours ago Exited (1) 3 hours ago youthful_galileo f07cd430c93f ubuntu "bash" 3 hours ago Exited (100) 3 hours ago flamboyant_gauss 00797699839d ubuntu "bash" 3 hours ago Exited (0) 3 hours ago mystifying_haibt 8c43d7de8a61 ubuntu "bash -v /Users/kamu…" 3 hours ago Exited (127) 3 hours ago pensive_driscoll d9dd49abc9a2 ubuntu "bash -e DISPLAY=loc…" 3 hours ago Exited (1) 3 hours ago sad_haslett c87d6fa7033f ubuntu "bash" 3 hours ago Exited (127) 3 hours ago dazzling_dirac 211966417e8b ubuntu "bash" 3 hours ago Exited (129) 3 hours ago happy_kilby 25894b2736b4 ubuntu "bash" 4 hours ago Exited (127) 3 hours ago dreamy_pike 1638b28b41bb hello-world "/hello" 4 hours ago Exited (0) 4 hours ago sharp_proskuriakova # 停止中のコンテナをまとめて破棄する % docker container prune -f Deleted Containers: 9c8d40b83710131bb740b5ff1d47d967cbcd2630f7a3b847c85ff10239542353 c5f2445da776b9cd35b9f0e0a5ee3d2a333d27c3e6ac6d5cd8cce7151ea5e9db 5eeb98e955246b72bfc8867dbd7ac544b10b70650a664b18f5e15e4175aa751d 00945096ebc44d0c5cd0c7ef6a729db2a341f357effb88657a23659348c51627 1a7cf61e220322cff6716ee5281d52040e161a9bc9b753311c6ec6a48d45de95 f07cd430c93f8509273fe33e0dc66343d1cbd18211e0fed0dabc75005a977b5f 00797699839d80c0884efe35b957b1df4d4417d56cab044d30215b53db168990 8c43d7de8a6128a8304cf1d34f761a9327d3244a64fad267d7fb023665452c95 d9dd49abc9a29a8b1e083581c658ed92bdf173ce58977f4afc96ced2a2d7bab4 c87d6fa7033f9e547f23c64c13e24e713f5d1a407e8aa8d7631b99fbb081ef16 211966417e8bcb48dac2dd165ad2ed0693d3facd381c2df1f5f84e4eda1c82b2 25894b2736b441195b712c2e4688b8ce0a5f22e5e834b162cdec8b4c11d231ac 1638b28b41bbb9b29d5dfd2fb347bd2ace7c7f8dcbbad0c948eb1fb63282119e Total reclaimed space: 507.7MB # 削除されていることを確認 % docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 四苦八苦してubuntuコンテナをたくさん作ったが、それでも507MB。かなり軽い(何もパッケージ入ってないけど)。 ひとまずここまで。もう少しdockerを掘り下げて、Dockerfileの作成を行いたい。
- 投稿日:2021-05-16T22:02:14+09:00
C/C++の軽量なDocker実行環境の作り方
概要 C/C++のプログラムをDockerコンテナでビルド、動作させる際の軽量な方法を紹介します。Dockerの実行環境の構築方法としては、Go、Python、Javaなどに関しては情報が多くあるのですが、C/C++に対しての良いDocker環境の構築方法の記事がなかったので共有します。 最近は、Dockerにmulti stage buildという機能があり、2段階でのDockerイメージの作成を行います。主に、Dockerfile内で一段階目で実行ファイルを作成するためのビルド環境を作成し、二段階目で、作成した実行ファイルを実行するためだけの軽量ランタイム環境を最終的なDockerイメージとして保存することが主流になってきています。これらをC/C++プログラムにも適用します。 また、最近ではdistolessイメージという、実行に特化して機能が限定された、軽量でセキュアなDockerイメージをGoogleが公開しております。詳しくは、こちらで詳しく解説している方がいらっしゃいます。この環境を使いたいのですが、C/C++では実行時にライブラリをリンクさせる動的リンクライブラリを使用する場合があり、その場合は、追加でパッケージを入れることが難しいdistoless環境ではプログラムの実行ができません。そのため、ここでは、他に軽量と言われていて、パッケージ追加など基本的な機能があるディストリビューションのAlpine Linuxを使います。Alpine Linuxについて詳しくは、こちらで解説されている方がいらっしゃいます。 もし、より良いDockerの実行環境があればコメント頂ければ幸いです。 Dockerfileと実行方法 まず、Dockerfileとその実行方法を示して、そのあとにDockerfileの意味を一つ一つ説明していきます。以下のDockerfileを作成します。 # --------------- # Image creation stage FROM alpine AS dev # Copy required files COPY ./simulation.cpp /app/ # Set the working directory WORKDIR /app # Install required packages RUN apk add --quiet --no-cache \ librdkafka-dev \ alpine-sdk \ nlohmann-json # Build RUN g++ simulation.cpp -o simulation -lrdkafka++ # --------------- # Image creation stage FROM alpine AS prod # Set the working directory WORKDIR /app # Copy required files COPY --from=dev /app/simulation /app/simulation # Install required packages RUN apk add --quiet --no-cache \ librdkafka-dev # --------------- # Execution CMD ["./simulation"] Dockerイメージのビルドと起動を行います。同じディレクトリにコンパイル、実行したいプログラムsimulation.cppを置いておきます。 docker build -t simulation:1.0 . docker run -it simulation:1.0 作成された実行環境のDockerイメージが以下のsimulationで、参考として、<none>がビルド環境、ubuntuがubuntuイメージです。simulationが非常に軽量なのがわかります。 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE simulation 1.0 3593bd8b0d91 About a minute ago 13.1MB <none> <none> 64d875c1b27f 11 minutes ago 227MB ubuntu latest 7e0aa2d69a15 3 weeks ago 72.7MB Dockerfileの説明 alpineのイメージを作成し、devとタグを付けます。 # Image creation stage FROM alpine AS dev ローカルの現在のディレクトリからdevの/app/のディレクトリに対してsimulation.cppをコピーします。 # Copy required files COPY ./simulation.cpp /app/ 作業用ディレクトリを/appに変更します。(cdのようなものです。) # Set the working directory WORKDIR /app ビルドに必要なパッケージをインストールします。私のsimulation.cppのビルドに必要なパッケージを記載しているだけなので、パッケージ部分は任意に書き換えて下さい。no-casheを指定することで、パッケージをキャッシュしない設定となり、通常イメージサイズ削減のため指定する。quietは特にapk addの出力などが必要ない時に指定する。 # Install required packages RUN apk add --quiet --no-cache \ librdkafka-dev \ alpine-sdk \ nlohmann-json Docker内でコンパイルを行う。-lrdkafka++により動的リンクするライブラリを指定する。 # Build RUN g++ simulation.cpp -o simulation -lrdkafka++ 次に、実行用のDockerイメージを作成する。prodとタグを付ける。 # Image creation stage FROM alpine AS prod 作業用ディレクトリをprodの/appとする。 # Set the working directory WORKDIR /app devのイメージから実行ファイルをprodにコピーする。 # Copy required files COPY --from=dev /app/simulation /app/simulation 動的リンクが必要なライブラリのみをインストールする。 # Install required packages RUN apk add --quiet --no-cache\ librdkafka-dev 実行ファイルを実行する。 # Execution CMD ["./simulation"] 以上です。
- 投稿日:2021-05-16T21:38:03+09:00
【MySQL】Docker 日本語化 SQL 学習メモ
MySQL環境構築 MySQLの起動 # mysqlのイメージ取得 $ docker pull mysql # コンテナ作成・起動 $ docker run -it --name ${任意のコンテナ名} -e MYSQL_ROOT_PASSWORD=${任意のmysqlパスワード} -d mysql:latest # mysqlコンテナのshellに入る $ docker exec -it ${上記で設定したコンテナ名} bash # mysqlにログインパスワードは、上記で設定したもの $ mysql -u root -p MySQLの日本語対応(コマンドラインで日本語が入力できないため) $ locale -a | grep ja # 設定されていないため以下の表記 locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_COLLATE to default locale: No such file or directory # 必要なものインストール $ apt-get install locales dialog # 設定 $ dpkg-reconfigure locales $ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 $ export LC_ALL=ja_JP.UTF-8 $ locale -a | grep ja # 以下の設定になっていればOK ja_JP ja_JP.utf8 Sampleデータベース、テーブル作成 -- データベース作成 CREATE DATABASE shop; -- 商品テーブル作成 CREATE TABLE shohin ( shohin_id CHAR(4) NOT NULL PRIMARY KEY, shohin_mei VARCHAR(100) NOT NULL, shohin_bunrui VARCHAR(32) NOT NULL, hanbai_tanka INT, shiire_tanka INT, torokubi DATE ); -- データ挿入 BEGIN; insert into shohin values ('0001', 'Tシャツ', '衣服', 1000, 500, '2009-09-20'); insert into shohin values ('0002', '穴あけパンチ', '事務用品', 500, 320, '2009-09-11'); insert into shohin values ('0003', 'カッターシャツ', '衣服', 4000, 2800, NULL); insert into shohin values ('0004', '包丁', 'キッチン用品', 3000, 2800, '2009-09-20'); insert into shohin values ('0005', '圧力鍋', 'キッチン用品', 6800, 5000, '2009-01-15'); insert into shohin values ('0006', 'フォーク', 'キッチン用品', 500, NULL, '2009-09-20'); insert into shohin values ('0007', 'おろしがね', 'キッチン用品', 880, 790, '2009-04-28'); insert into shohin values ('0008', 'ボールペン', '事務用品', 100, NULL, '2009-11-11'); COMMIT; -- 商品2テーブル作成 CREATE TABLE shohin2 ( shohin_id CHAR(4) NOT NULL PRIMARY KEY, shohin_mei VARCHAR(100) NOT NULL, shohin_bunrui VARCHAR(32) NOT NULL, hanbai_tanka INT, shiire_tanka INT, torokubi DATE ); -- データ挿入 BEGIN; insert into shohin2 values ('0001', 'Tシャツ', '衣服', 1000, 500, '2009-09-20'); insert into shohin2 values ('0002', '穴あけパンチ', '事務用品', 500, 320, '2009-09-11'); insert into shohin2 values ('0003', 'カッターシャツ', '衣服', 4000, 2800, NULL); insert into shohin2 values ('0009', '手袋', '衣服', 800, 500, NULL); insert into shohin2 values ('0010', 'やかん', 'キッチン用品', 2000, 1700, '2009-09-20'); COMMIT; -- 店舗テーブル作成 CREATE TABLE tenposhohin( tenpo_id CHAR(4) NOT NULL, tenpo_mei VARCHAR(200) NOT NULL, shohin_id CHAR(4) NOT NULL, suryo int NOT NULL, PRIMARY KEY(tenpo_id, shohin_id) ); -- データ挿入 BEGIN; INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000A', '東京', '0001', 30); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000A', '東京', '0002', 50); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000A', '東京', '0003', 15); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000B', '名古屋', '0002', 30); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000B', '名古屋', '0003', 120); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000B', '名古屋', '0004', 20); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000B', '名古屋', '0006', 10); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000B', '名古屋', '0007', 40); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000C', '大阪', '0003', 20); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000C', '大阪', '0004', 50); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000C', '大阪', '0006', 90); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000C', '大阪', '0007', 70); INSERT INTO tenposhohin (tenpo_id, tenpo_mei, shohin_id, suryo) VALUES('000D', '名古屋', '0001', 100); COMMIT; 商品テーブル shohin_id shohin_mei shohin_bunrui hanbai_tanka shiire_tanka torokubi 0001 Tシャツ 衣服 1000 500 2009-09-20 0002 穴あけパンチ 事務用品 500 320 2009-09-11 0003 カッターシャツ 衣服 4000 2800 NULL 0004 包丁 キッチン用品 3000 2800 2009-09-20 0005 圧力鍋 キッチン用品 6800 5000 2009-01-15 0006 フォーク キッチン用品 500 NULL 2009-09-20 0007 おろしがね キッチン用品 880 790 2009-04-28 0008 ボールペン 事務用品 100 NULL 2009-11-11 商品テーブル2 shohin_id shohin_mei shohin_bunrui hanbai_tanka shiire_tanka torokubi 0001 Tシャツ 衣服 1000 500 2009-09-20 0002 穴あけパンチ 事務用品 500 320 2009-09-11 0003 カッターシャツ 衣服 4000 2800 NULL 0009 手袋 衣服 800 500 NULL 0010 夜間 キッチン用品 2000 1700 2009-09-20 SELECT文 実行順序 FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY 集約関数 *NULLは除外される。 Count関数 -- 全選択 -> 6 SELECT COUNT(*) FROM shohin; -- カラム指定 -> 8 SELECT COUNT(shiire_tanka) FROM shohin; -- 重複別 -> 3 SELECT COUNT(DISTINCT shohin_bunrui) FROM shohin; Min/Max関数 Avg関数 Sum関数 GROUP BY *SELECT句は、GROUP BYの後に実行されるため、AS句は使えない。 商品分類ごとにグループ化 SELECT shohin_bunrui COUNT(*) FROM shohin GROUP BY shohin_bunrui; Having *WHERE句でも同じ絞り込みができる場合は、WHERE句に記述する。 →COUNT関数が走るときにソートが行われるため(処理が重くなる)。 商品分類ごとでカウントが2つのもの SELECT shohin_bunrui COUNT(*) FROM shohin GROUP BY shohin_bunrui HAVING COUNT(*) = 2; 商品分類ごとで販売単価平均が2500以上 SELECT shohin_bunrui, AVG(hanbai_tanka) FROM shohin GROUP BY shohin_bunrui HAVING AVG(hanbai_tanka) >= 2500; ORDER BY句 AS句が使える SELECT文の一番最後に書く 集約関数も利用可能 SELECT shohin_bunrui, COUNT(*) FROM shohin GROUP BY shohin_bunrui ORDER BY COUNT(*); INSERT insert into .... selectで他テーブルへコピー。集計関数も使用可能 DELETE 全権削除の場合、TRUNCATEの方が高速。 ビュー SELECT文を保存可能 サブクエリ FROM句にSELECT文書ける スカラサブクエリ 戻り値が単一なので条件にかける SELECT * FROM shohin WHERE habai_tanka > (SELECT AVG(hanbai_tanka) FROM Shohin); 相関サブクエリ 戻り値が複数ある時の比較(小分けしたグループ内での比較) 述語 LIKE 前方WHERE shohin_mei LIKE 'カ%'; 中間WHERE shohin_mei LIKE '%カ%'; 後方WHERE shohin_mei LIKE '%カ'; 任意の文字数WHERE shohin_mei LIKE '_カ_'; BETWEEN 範囲検索WHERE hanbai_tanka BETWENN 100 AND 1000; *両端の値も含む(100<=x<=1000)。 IS NULL, IS NOT NULL WHERE hanbai_tanka IS NULL; WHERE hanbai_tanka IS NOT NULL; IN, NOT IN サブクエリが使える。 WHERE hanbai_tanka IN (320, 500, 5000); WHERE hanbai_tanka NOT IN (320, 500, 5000); EXISTS 必ず相関サブクエリを引数に取る CASE式 テーブル同士の操作 集合演算 テーブルの演算(行の操作) UNION 和集合(UNION ALLで重複行表示) ORDER BYは共通で1つ SELECT shohin_id, shohin_mei FROM shohin UNION ALL SELECT shohin_id, shohin_mei FROM shohin2 INTERSECT 未対応 EXCEPT 未対応 結合(列の操作) 内部結合 両方のテーブルに情報が存在するもの SELECT TS.tenpo_id, TS.tenpo_mei, TS.shohin_id, S.shohin_mei, S.hanbai_tanka FROM tenposhohin AS TS INNER JOIN shohin as S ON TS.shohin_id = S.shohin_id; 外部結合 どちらかのテーブルに情報が存在するもの LEFT, RIGHTどちらをマスタにするか SELECT TS.tenpo_id, TS.tenpo_mei, TS.shohin_id, S.shohin_mei, S.hanbai_tanka FROM tenposhohin AS TS RIGHT OUTER JOIN shohin as S ON TS.shohin_id = S.shohin_id; -- 3テーブル FROM tenposhohin AS TS INNER JOIN shohin as S ON TS.shohin_id = S.shohin_id INNER JOIN zaikoshohin as ZS ON TS.shohin_id = ZS.shohin_id;
- 投稿日:2021-05-16T17:27:22+09:00
Cloud9の開発前準備(容量削減)
はじめに Cloud9にて開発を実施していく中でディスク不足が原因で様々な問題を引き起こしてしまったので、開発着手前に事前に設定しておくべき内容を記載しておきます。 ディスク不足によるエラーに関しては以下内容をご参照ください。 https://qiita.com/YotaHamasaki/items/a7ce6bc4039607e3a389 https://qiita.com/YotaHamasaki/items/a9b2093eeee44057aeef 設定内容 ①dockerイメージの削除 ②メモリの解放 ③swap領域設定 ④ボリュームの追加 ①dockerイメージの削除 ワークスペース作成時にはdockerイメージが初期状態で入っています。 これが容量を大きく圧迫しているので、dockerにて環境構築しない場合、削除してしまった方が良いと思います。 コマンドは以下になります。 $ docker rmi `docker images -q` ②メモリの解放 メモリの容量不足によりプログラム実行時にエラーが発生することがあるので、こちらも実施しておいた方が良いと思います。 $ sudo sh -c "echo 3 > /proc/sys/vm/drop_caches" ③swap領域設定 swap領域はHDD上の仮想的なメモリで、実メモリの使用量を超えた分を一時的に書き出す場所です。 こちら領域の設定をしておきましょう。 $ sudo dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 $ sudo chmod 600 /var/swap.1 $ sudo mkswap /var/swap.1 $ sudo swapon /var/swap.1 $ sudo cp -p /etc/fstab /etc/fstab.ORG $ sudo sh -c "echo '/var/swap.1 swap swap defaults 0 0' >> /etc/fstab" ④ボリュームの追加 HDDの容量不足を防ぐために、HDDの容量追加を行います。 これはEC2インスタンスの設定変更にて、ボリュームを増やすことで実現します。 この手順としては以前記事にしていたので、そちらをご参照いただければ幸いです。 https://qiita.com/YotaHamasaki/items/a7ce6bc4039607e3a389 そしてインスタンスタイプの変更ができたら、次はターミナル上で以下コマンドを入力して、HDDの容量が設定した容量となります。 $ sudo growpart /dev/xvda 1 $ sudo resize2fs /dev/xvda1 無駄な容量を喰わないように開発前から準備する大切さを学びました。
- 投稿日:2021-05-16T14:28:12+09:00
.netCore + Angular環境をDockerで構築
はじめに バックエンド:.NetCore、フロントエンド:Angular で開発する機会があったのでどうせならDockerで作ろうと思いました。 そこそこネット上に情報あるのですが、実際にやってみたら結構手間取ったので手順を残しておきます。 (Docker自体はもともと入れていたので省略) 概要 やること .NetCoreのimageを取得 imageからコンテナを作成 プロジェクト作成 いろいろ入れる サーバ起動 作業 .NetCoreのimageを取得 Microsoft公式のDockerHubからimageを取得しました どれを入れれば良いのか迷いましたが dotnet/sdk で問題なさそうです。 docker pullでimageを取得します。 docker pull dotnet/sdk imageからコンテナを作成 (知識不足もあって)ここでだいぶ嵌りました。。後工程でサーバ起動時にポート問題でホスト側からアクセスできず。 .NetCore起動時にhttp:5000, https:5001のポートを使っていてhttpsに自動的にリダイレクトするようです。 コンテナ作成時に5000と5001両方使えるようにしました。 docker run --name dotnet -it --mount type=bind,src=$(pwd)/dotnet,dst=/vol -p 5000:5000 -p 5001:5001 mcr.microsoft.com/dotnet/sdk mountとかnameとかはお好みで プロジェクト作成 適当にディレクトリ切って.NetCoreプロジェクトを作成します。 new の後にangularといれるとangular用のテンプレートプロジェクトが作成されます。 参考:https://docs.microsoft.com/ja-jp/aspnet/core/client-side/spa/angular?view=aspnetcore-5.0&tabs=visual-studio dotnet new angular いろいろ入れる node angularの実行にnode.jsが必須のためインストールします。 使用したimageはDebian環境でそのままnodeのインストールができなかったので下記参考にインストールしました。 参考:https://qiita.com/naoyukiyama/items/29054cff00923f9543ce curl -sL https://deb.nodesource.com/setup_10.x | bash apt install -y nodejs Angular 入れていない状態でもAngular用プロジェクト作成はできるようです。 AngularCliのバージョンは使いたいものがあれば指定しておいた方が良いです。 (後からバージョンアップはできるがダウングレードは入れ直しになってしまうので) npm install -g @angular/cli@11.1.0 サーバ起動 これで起動できるのですが、ホストから接続するためにもうひと手間 開発環境では.NetCore側でlocalhostからのアクセスしか許容していないのでそこを解放します。 参考:https://mseeeen.msen.jp/asp-net-core-3-allow-access-to-kestrel-from-outside-in-development-mode/ appsettings.jsonに「"urls": "http://:5000;https://:5001",」を追加 { "urls": "http://*:5000;https://*:5001", "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" } 起動します。 dotnet run 実行時に下記のようにlistenできていればOK ホスト側ブラウザからアクセス http://localhost:5000 HelloWorld画面が表示されれば環境構築完了です!
- 投稿日:2021-05-16T14:18:59+09:00
Spring + MySQL を用いたREST APIのDocker化メモ
SpringとMySQLを利用したREST APIをDockerで動作させた際のメモ Springで作成したAPIをDockerで動作するTomcatにデプロイし、同じくDockerで動作するMySQLに接続させる。 プロジェクト構成 ルート │ docker-compose.yml │ ├─ap │ └─docker │ │ Dockerfile │ │ │ └─webapps │ rest.war │ └─db └─docker └─db │ my.cnf docker-compose.yml version: "3" services: ap: build: ./ap/docker image: rest_api_image container_name: tomcat_container ports: - 8080:8080 links: - db db: image: mysql:5.7 container_name: mysql_container environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: sample_db MYSQL_USER: mysqluser MYSQL_PASSWORD: mysqlpass volumes: - ./db/docker/db/data:/var/lib/mysql - ./db/docker/db/my.cnf:/etc/mysql/conf.d/my.cnf restart: always ports: - 3306:3306 ap Dockerfile FROM tomcat:8.5.35 EXPOSE 8080 RUN useradd -s /sbin/nologin tomcat RUN chown -R tomcat:tomcat /usr/local/tomcat USER tomcat COPY webapps/rest.war /usr/local/tomcat/webapps/ CMD ["catalina.sh", "run"] rest.war こちらで作成したAPIを以下のように改修し.warファイルにビルドする。 改修箇所 エントリポイント(UserApplication) SpringBootServletInitializerクラスを継承させ、configureメソッドをoverrideさせる。 package com.example.restservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication @EnableJpaAuditing public class UserApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(UserApplication.class); } } pom.xml 以下を追加。 <packaging>war</packaging> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> DB接続設定(application.properties) localhostではなく、DBコンテナ名を指定する。 spring.datasource.url=jdbc:mysql://mysql_container:3306/sample_db spring.datasource.username=mysqluser spring.datasource.password=mysqlpass spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver db my.cnf 文字コード指定 [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] default-character-set=utf8mb4 動作確認 1.コンテナを起動する。 docker-compose up 2.DBにテーブルを作成する。 こちらのSQLを実行し、テーブルを作成する。 3.APIを呼び出す。 ※呼び出しの際には、http://localhost:8080/{warファイル名}/api/users となる点に注意する。 ユーザー登録API(POST /rest/api/users) リクエスト POST /rest/api/users HTTP/1.1 Host: localhost:8080 Content-Type: application/json Content-Length: 24 { "name":"test4" } レスポンス { "id": 4, "name": "test4" } ユーザー取得API(GET /rest/api/users/{user_id}) リクエスト GET /rest/api/users/4 HTTP/1.1 Host: localhost:8080 Content-Type: application/json レスポンス { "id": 4, "name": "test4" } ユーザー一覧取得API (GET /rest/api/users) リクエスト GET /rest/api/users HTTP/1.1 Host: localhost:8080 Content-Type: application/json レスポンス [ { "id": 1, "name": "test" }, { "id": 2, "name": "test2" }, { "id": 3, "name": "test3" }, { "id": 4, "name": "test4" } ] 詰まったところ 404 Not Found 以下の対応を行った。 Dockerfileにtomcatユーザーを作成し、権限設定する処理を記述(参考)。 エントリーポイントクラスにSpringBootServletInitializerクラスを継承させ、configureメソッドをoverride(参考)。 参考情報 Spring BootでWARを作成して別のTomcatにデプロイする
- 投稿日:2021-05-16T13:26:20+09:00
モダンな技術を使ってRailsアプリを開発、デプロイするまでのロードマップ2021
はじめに この記事はモダンな技術(後述)を使用してRailsアプリケーションを開発し、AWS上にデプロイするまでの学習手順を詳細にまとめたものです。基本的に参考になる記事、書籍を編纂し、自分がわかりにくかったと感じた部分は自分で記事を書いています。リンクの記事を書いてくださった方々には本当に感謝です。 この記事の目的 新しいことを独学しようとすると一つ大きな問題があります。それは計画通りに実行するのが困難であるということです。自分のすべき作業が明確化されていないことによって、 1. どのくらいで終わるのかを数値化することが困難 2. エラーを予測できない 3. そもそも次になにをすべきかわからず、それを決定するのに時間を要する などの問題が発生します。私自身インフラの学習からアプリ開発、デプロイ完了までの期間が予定よりも2ヶ月近く伸びしまいました。 この記事は次にやるべきことを明確化することによって、以上のような計画錯誤を減らすことを目的としています。計画術についてはDaiGoさんの書籍が参考になるかと。 この記事で紹介する言語、フレームワーク、その他技術 フロント関連 HTML CSS Sass JavaScript jQuery Vue.js Ruby on Rails MySQL nginx Docker AWS IAM VPC ELB Route 53 RDS S3 ECR ECS CloudWatch Systems Manager Certificate Manager Terraform CircleCI 留意事項 前提知識は特に必要ありません。必要ないところは読み飛ばしてください。 環境はWSL(Windows Subsystem for Linux)です。Macを使用している方は導入に関する部分はご自身で調べてください。 技術の独学について 新しい技術を独学するには以下のような方法が効率的です(経験則ですが)。 基礎知識を身に着けます。具体的には"〇〇 入門"とかで検索すると入門者向けの記事が見つかるのでそれを読むとよいかと。 次にハンズオン学習を行います。言い換えればチュートリアルです。実際に触って基本操作を身に着けます。 チュートリアルをクリアしたら書籍を一冊読むなどして体系的知識を身に着けます。 5. 公式ドキュメントをみながら実践を行います。 Column 「学んだことはすぐに忘れてしまう!だから技術を学ぶにはとにかくスピードが大事なのだ!」 それは短期記憶向きの学習法しか実践していないからだと思います。長期的に記憶を維持したい場合には検索練習を行いましょう。検索練習に関してはパレオさんのブログを参照。個人的にはエクセルなんかに検索練習しておくと忘れたときにチートシートして使えるのでおすすめ。 「完全に理解しようとするのは効率が悪い!だから理解せずともどんどん先に進めるべきだ!」 確かにRailsチュートリアルとかちゃんと理解しながら進めようとするとめちゃくちゃ時間かかるんですよね。かといってこの言葉を鵜呑みにしてもエラーばっかでやる気が削がれてしまうのかなと。なのでハンズオン系の学習に関しては適切な難易度設定を意識してみるとよいかと思います。こちらもパレオさんのブログを参照下さい。 ロードマップ 1. ITに関する基礎知識を学ぶ ようやくここから本題です。まずITに関する基礎知識を勉強しますが、正直ここはしっかり勉強しようとしなくていいです。なんせ情報が多いので。キタミ式等の書籍をざっくり読んで、後々わからない言葉等が出てきたときにその都度「そういえばそんなことあの本に書いてあったな...」で読み返せばいいと思います。 2. HTML, CSS, Sassの基礎知識、チュートリアル Webページをつくるための言語です。Progateを利用して学習しましょう。 3. JavaScript, jQueryの基礎知識、チュートリアル Webページを動的にするために使用します。Progateで。 4. エディターの導入、ショートカット、マルチカーソルの利用 ローカル(自分のPC)にエディターを導入します。色々ありますが迷ったらVSCodeを入れておけばよいかと。 またショートカット、マルチカーソルを利用するとコーディングを効率よく行えます。 Visual Studio Code キーボードショートカット一覧(チートシート) VSCodeのマルチカーソル練習帳 5. HTML、CSSを使ってモダンなコーディングができるようになる "HTML5/CSS3モダンコーディング"という書籍をクリアすると基本的につくりたいようなページは自分で制作できるようになると思います。 6. CSSの設計方法を学ぶ CSSはシンプル故にコードが煩雑になりやすいです。"CSS設計の教科書"という書籍を読みましょう。特にBEMとFLOCSSを抑えておくとよいかと思います。 7. Flexbox FlexboxはCSSのレイアウト方法です。"HTML5/CSS3モダンコーディング"ではfloatプロパティを使って要素の横並びを行っていますが、Flexboxを使えば簡単に実装できます。実際にページを作る際に利用す際にチートシートをみて利用するとよいでしょう。 8. SQLの基礎知識、チュートリアル データベースを操作するためのクエリ(一連の問い合わせ)です。Progateで。 9. Rubyの基礎知識、チュートリアル Webアプリケーションのロジックをつくるための言語です。Progateで。 10. Ruby on Railsの超基礎知識、チュートリアル Rubyで書かれたWebアプリケーションフレームワークです。Progateで。 11. コマンドライン操作の基礎知識、チュートリアル コマンドを使ってファイル操作等を行います。ProgateのCommand Lineコースを利用して学習しましょう。 12. Gitの基礎知識、チュートリアル ソースコードのバージョン管理システムです。Progateだけだと心許ないのでドットインストールのgit入門もクリアしておくとよいかと思います。 13. Ruby on Railsチュートリアル 最初の山場です。Ruby on Railsチュートリアルをクリアしましょう。わからなくなっても調べれば有益な情報がいくらでも出てくるので挫折の心配はないかと思います。 14. 開発環境を構築する ローカル環境を構築します。WSLの基本については以下を参照。 【WSL入門】第1回 Windows 10標準Linux環境WSLを始めよう Ubuntuは無印版を推奨します。LTS版(20.04)ではVSCodeのいくつかの拡張機能をインストールできませんでした。 WSL でマウントしたファイルシステムでもパーミッションを扱えるようにする WSLはlinuxがWindowsの全てのファイルを含むCドライブをマウントする形を取っていますが、デフォルトではCドライブのファイルにパーミッションが付与されていません(これによって度々エラーが発生します。因みにこれはつまりlinux上で開発を行えばよいのですが、これをすると高負荷な処理をした場合にWSLがフリーズしたりします)。 WSL2によるホストのメモリ枯渇を防ぐための暫定対処 またDocker等を使用して開発するとWSLのVmmemというプロセスがメモリ使用量が肥大化し続け、ホストメモリが枯渇するという問題があります。 WSLでRails環境を構築する場合は以下を参照。 [Rails] Windows10 で WSL を使って Rails 環境を構築したときのメモ パッケージマネージャについては以下を参照。 パッケージ管理ツールをまとめてみる 15. linuxの基礎知識 "linux標準教科書"というのが無料でダウンロードできるのでそちらをさくっと読んでしまうのがよいと思います。後は今後パーミッション、ソケット通信等を扱うのでそちらの知識やコマンドも合わせて抑えておくとよいです。 Linuxの権限確認と変更(chmod)(超初心者向け) インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識 Unixドメインソケット PATHを通すために環境変数の設定を理解する (Mac OS X) Linuxディレクトリ構造 まとまった記事 “応用力”をつけるためのLinux再入門 16. Web技術の基礎知識 個人的には"イラスト図解式 この一冊で全部わかるWeb技術の基本"という書籍がよくまとまっていてわかりやすいと思いました。しかも安い。 上のような入門者向けの本を読んだら、次はWeb系エンジニア必読書と言われる"Webを支える技術"という書籍を読みましょう。 17. Ruby on Railsを体系的に学ぶ "パーフェクトRuby on Rails"はRuby on Railsガイドをハンズオン形式で学習できるような内容となっています。この書籍を読むことでRailsの基本的な概念に対する理解を深め、Rails付属の機能を扱えるようになります。コンテナやCIに関する内容も参考になりますが、この段階ではまだ未学習(のはず)なので、後々読んでみるとよいかと思います。 18. JavaScript本格入門 "JavaScript本格入門"を読めばES6でJavaScriptをそれなりに書けるようになると思います。手元にあるとどうやって書くんだったかわからなくなったときに便利。 19. JavaScriptスタック JavaScriptのツール全般(Node, NPM, Yarn等)についての知識です。 JavaScript Stack from Scratch 日本語訳は以下 ゼロから始めるJavaScript生活 Webpackについては"webpack 実践入門"という書籍が参考になります。 20. Vue.jsの基礎知識、チュートリアル SPAを構築するために使用します。あくまでRailsアプリにSPAを実装することが目的なので、基本のオプションとライフサイクル、コンポーネント間のデータフローを抑えておけば問題ないかと思います。学習の仕方としては"21Stepで体得 Vue.jsハンズオン"の1章、Step6, 11, 16を読んでやってみるとよいかと。 Railsへの導入方法は以下を参照。 Vue.js チュートリアル for Rails エンジニア(Vue3 version) またaxiosに関しては以下を参照。 [フロントエンド] axiosライブラリを使って、柔軟にHTTP通信を行う 21. ローカルで一度アプリケーションを作ってみる ここで一旦Railsアプリケーションをつくってみましょう。この作業の目的は 1. 自分でRailsのコードが書けるようになること 2. アプリケーションの要項の洗い出し です。なのでこの段階ではアプリはガバでいいです。次つくるときにテスト駆動開発しましょう。 因みに要項を洗い出す場合にはマインドマップが役立ちます。 22. Dockerの基礎知識、チュートリアル コンテナ仮想化を用いてアプリを開発するためのソフトです。私は"自宅ではじめる Docker入門"という書籍をやりました。Dockerfile, Docker Composeまでよくまとまっています。また"Docker/Kubernetes実践コンテナ開発入門"という書籍が有名?ですが入門者向きじゃないです。ただ(本番環境においても)コンテナ技術を使用するメリットを理解できるので、最初の章だけ読んでおけばいいんじゃないかと。 23. nginx、pumaの基礎知識 Railsアプリの前段にリバースプロキシとして使用するWebサーバです。pumaとソケット通信させて使用します。"nginx実践ガイド"という本を読みましょう。pumaの使い方に関しては以下を参照。 Pumaの使い方 まとめ 24. MySQL入門 RDBMSです。"MySQL徹底入門"という本を読みましょう。Docker Composeで扱う場合、主に関心事になるのは接続の仕方なのでユーザー管理の章を読んでおくといいと思います。因みに"基礎からのMySQL"という本もありますが、これは主にクエリについてまとめた本です(知らずに買いました)。 またRailsチュートリアルではサブクエリをそのまま文字列として記述していますが、ActiveRecord::Relationオブジェクトは最終的にサブクエリとして展開されるので、基本的にSQL文をそのまま書くことはないと思います(多分)。 参考 railsチュートリアル サブセレクトでなぜ高速化するのか 25. Dockerを使用した開発環境を構築する ここが鬼門です。なんせRails, nginx, MySQL, Dockerの知識をここで集約する必要があるので。後々自分でも解説記事を書こうと思います。 参考 Docker + Rails + Puma + Nginx + MySQL 26. AWSインフラ構築入門 ここからは本番環境での運用を目的としたインフラを構築するための学習になってきます。"Amazon Web Services 基礎からのネットワーク&サーバー構築"か"AWSではじめるインフラ構築入門"またはその両方をクリアしておくとよいと思います。正直何も考えなくても手さえ動かせばできてしまうのでしっかり検索練習しときましょう。 初期設定まわりは以下を参照。 AWS-CLIの初期設定のメモ AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ リソースを削除する場合は以下を参考に。 全リージョンから全リソースを一括検索する方法【タグエディター】 全部消したと思って放っておくと一部のリソースが残っていてキャッシュから毎月数千円とかしょっぴかれてる場合があるのでご注意下さい(経験談)。 27. ECS, ECR基礎知識、チュートリアル 上で紹介した書籍ではコンテナ技術を使っていないのでECS, ECRも触っておきましょう。 初心者でもできる! ECS × ECR × CircleCIでRailsアプリケーションをコンテナデプロイ 28. Terraform入門、実践 TerraformとはIaC(Infrastructure as Code)を実現するためのものです。"実践Terraform"という書籍をクリアしましょう。正直Terraformを使用しなくてもデプロイはできるのですが、なぜTerraformを学習するとよいのかというと 1. 冪等性を利用して、破壊、再構築を何度でもできる。 2. 必要な情報のみをコード化して扱うのでロジックを理解しやすい。 3. 充実の公式ドキュメント の理由からです。 まず1について。インフラを運用する場合当然お金がかかります。因みにステージング環境と本番環境をESC、RDSのみ2つ用意し、それ以外の構成をホストベースルーティングで共有する環境を構築したとして、最低スペック、ほぼ未稼働で24時間あたりだいたい9ドル以上、日本円で1000円前後かかります。ただこれをコンソールで管理した場合、依存関係を認識しないとろくに削除もできないし、そもそもコンソールをいじっている時間だけ無駄です。 次に2について。これもすごく大きいです。コンソールだと必要な情報が視覚的にまとまってないし、エラーもキャッチしにくいのでロジックを理解するのが難しいんですよ。対してコードで扱えば情報を自分でまとめられるし、構築時にエラーがちゃんとでるし、何よりコードを書いている間に理解が進みます。 最後に3について。 公式ドキュメントがユースケース付きでまとまってて、すごく見やすいしわかりやすい。コード自体も別に難しくないので学習コストはそんなかかりません。それよりも必要な知識はAWSです。よってAWSに関しては以下を参照。 AWS IAM IAMロールに関しては以下を参照。 【図解/AWS】初心者にも分かりやすいIAM入門~ロールとグループとポリシーの違い,設計・設定手順について~ AWS IAMポリシーを理解する IAM ロールの PassRole と AssumeRole をもう二度と忘れないために絵を描いてみた JSONポリシーに関しては以下を参照。 IAM JSON ポリシーの要素のリファレンス Fargate ECS Fargateに関しては以下を参照。 基礎から応用までじっくり学ぶECS Fargateを利用したコンテナ環境構築 #Fargate "実践Terraform"ではFargate PV1.3.0を使用していますが、最新版は1.4.0で最新版を使用するにはエンドポイントが必要です。以下を参照。 【衝撃に備えろ】Fargate PV1.4のVPCエンドポイント変更点について ECRにpushしたコンテナをECSFargateで使うVPCエンドポイントTerraform例 Amazon ECS インターフェイス VPC エンドポイント (AWS PrivateLink) 秘匿情報 秘匿情報に関しては以下を参考に Terraform × パラメータストアでRDSの機密情報をセキュアに扱う AWS Systems Manager パラメータストア ホストベースルーティング ステージング環境については以下を参照。 まともなステージング環境"を考える リスナールールでサブドメインとターゲットグループを紐付けられます。ホストベースルーティングについては以下を参照。 【新機能】ALBのHost-based routingを試してみた TerraformでAWS上にHTTPS化したサブドメインを定義する タスク定義 ECSのタスク定義に関しては以下。 タスク定義パラメータ Terraform またTerraformに関しては以下を参照。 DRY Rails学習後にTerraformを学習してなんだこれ全然DRYじゃないじゃないかと思った方はいるはず。TerraformをDRYに書く方法に関しては以下を参照。 Terraformで複数台のEC2インスタンスを構築する場合のTIPS ただこの記事はやや古いので最新の構文に関しては公式ドキュメントを参照。 他にもDynamicやforを使用することでDRYに書くことができます。 ディレクトリ設計 ディレクトリ設計に関しては以下を参照。 Terraformのディレクトリパターン集 Code structure JSON TerraformにはJSONオブジェクトなるものがあり、Terraform内の変数使ってJSONを記述できます。 JSON Configuration Syntax 29. Dockerを使用してテスト及び本番環境の構築 本番用のDocker環境を構築する上で必要になってくる知識は、 1. Credentials 2. アセットパイプライン の2つです。 またテスト用の場合にはブラウザテストの知識が必要です。 Credentials Railsで環境毎に秘匿情報を扱うためのものです。詳細は以下を参照。 利用環境のセキュリティ Rails 6よりサポートされたMulti Environment Credentialsをプロジェクトに導入する Rails 5 から 6 にかけての secretes / credentials 周りの変遷 アセットパイプライン アセットパイプラインとはjsやcssのアセットを集約するためのフレームワークです。詳細はRailsガイドを参照。特に"production環境の場合"という項目が重要です。 またFargateを利用する場合、開発環境のようにDockerボリュームを利用できないのでnginxとRails間で同じボリュームをマウントしアセットを共有するということができません。よってAssetSyncというgemを使用し、s3からアセットを配布します。AssetSyncに関しては以下を参照。 Asset Sync Asset Sync を Webpacker と連携させる 【Rails】asset_syncを利用してCloudFront + S3からアセットファイルを配信する またCORSに関しては以下を参照。 オリジン間リソース共有 (CORS) Using CORS ブラウザテスト ブラウザを利用したシステムテストに関しては以下が参考になります。 2020年のRailsでブラウザテストを「正しく」行う方法(翻訳) Rails用Dockerfileを構築する Dockerfileの構築に関しては以下が参考になります。 効率的に安全な Dockerfile を作るには クジラに乗ったRuby: Evil Martians流Docker+Ruby/Rails開発環境構築(翻訳) マルチステージビルドに関しては以下。 マルチステージビルドの利用 Multi-stage build でNode.jsのインストールをちょっぴり効率化する .dockerignoreに関しては以下。 .dockerignore file .dockerignoreが効かない?.gitignoreとは書き方が違うよ! またブラウザテストはdocker-seleniumを使用せずRailsと同じコンテナにchrome用のパッケージを入れることでも行えます。以下が参考になります。 Rails on Docker(alpine)でdocker-seleniumを使わないでSelenium+RSpec+Capybaraでテスト自動化してみる また本番環境用のDockerfile構築には以下が参考になります。 【Dockerfile全解説】Rails本番環境のための一番シンプルなDockerイメージを作る 30. CircleCIの基礎知識、チュートリアル CircleCI自体は難しくありません。ECS, ECRの場合、CircleCIのOrbsという機能を使えば簡単にデプロイできます。"CircleCI実践入門"という書籍を読みましょう。特に"Obrsを使った継続的デプロイの実践例"という項目をやっておくとよいと思います。 31. テスト(RSpec, Capybara) RSpec, Capybaraの書き方に関しては以下が参考になります。 使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 sleepやリトライに頼らない安定した feature spec を書こう Capybaraチートシート 公式ドキュメントは以下です。 RSpec Expectations 3.10 Capybara 32. アプリ開発開始 ここから実際にアプリをつくっていきます。新規プロジェクトを作成するときには以下の記事を参考に。 新規Railsプロジェクトの作成手順まとめ 33. 自動デプロイ Railsのディレクトリ内に.circleci/config.ymlをつくりCircleCIで自動テスト、自動デプロイを行えるようにします。以下の記事が参考になります。 【実践: 詳しくわかる】TerraformでCircleCIを通してAWSにECS環境を自動構築する方法 【CircleCI】【Terraform】【Rails】【AWS】Orbsを利用してECSでdb:migrateする方法 また公式のObrsは以下を参照。 circleci/aws-ecs circleci/aws-ecr 34. テスト駆動開発 あとはテスト駆動開発を進めていきます。 おわりに このロードマップは割とDeveloper Roadmapに沿ったものになっているかなと思います。改めてDeveloper Roadmapを見るとその有用性がわかります。ロードマップというのは順を追ってみていくのが普通ですが、このロードマップが真に有用である点は知識の依存関係がわかることです。目的の知識から逆順にたどっていくことで、それを理解するにはどんな知識が必要なのかある程度的を絞ることができます。独学をしてつまったときには一度、それにはどんな知識、技術が関わっているのかを考えてみるとよいかもしれません。 一から何かを独学しようなどというのはなかなか酔狂なことだと思いますが、この記事がそのような方の役に立てば幸いです。最後に改めて参考リンクの記事を書いてくださった方々に感謝です。有難うございました。
- 投稿日:2021-05-16T13:00:56+09:00
Rudi-NXにnvidia-docker2をインストールする
概要 Connect Tech社のRudi-NXは,Jetson Xavier NXを搭載した組み込み用ボードです.豊富な端子類と何よりファンレス構造が特徴の製品ですね.これでにDockerを入れてROSを動かそうと思ったときに,rvizがうまく起動しませんでした.諸々調べたところ,JetsonのcudaにDocker内からアクセスする際にはnvidia-docker2を使うのが主流らしいのですが,なぜかRudi-NXにプリインストールされているJetpackにはこれが入っていなかったので頑張ってインストールしてみよう,という記事です. 問題点 通常のJetsonシリーズであれば,公式サイトから自前でJetpackのイメージを落としてきてMicro SDに入れるわけですが,この場合は特別な手順を踏むことなく自動的にnvidia-docker2がインストールされた環境が出来上がります. Rudi-NXの場合は工場出荷状態でOSが入っていますが,これにnvidia-docker2はインストールされていませんでした.更に調べたところ,Rudi-NXの場合は工場出荷時点でaptのsourceslistが変更されているため,apt install nvidia-docker2してもパッケージが見つからず自前でインストールもできません.そこで,以下のように修正し,通常のJetpackと同じものをインストールできるようにします. 手順 まずは設定ファイルを開きます. sudo vim /etc/apt/sources.list.d/nvidia-l4t-apt-source.list 続いて,中身を以下の状態に変更し保存します. /etc/apt/sources.list.d/nvidia-l4t-apt-source.list deb https://repo.download.nvidia.com/jetson/common r32.4 main deb https://repo.download.nvidia.com/jetson/t194 r32.4 main 出荷状態ではこれらがコメントアウトされていたので,それを解除しました. 次にこれらの認証キーを取得します. sudo apt-key adv --fetch-key http://repo.download.nvidia.com/jetson/jetson-ota-public.asc 最後にupdateをかければ,aptでnvidi-docker2をインストールできます. sudo apt update sudo apt install nvidia-docker2 これでdocker内からcudaコアにアクセスするアプリケーションが走ります.お疲れ様でした. 参考 sourcelistの編集と認証キーの取得についてはここを参考にしました. https://forums.balena.io/t/getting-linux-for-tegra-into-a-container-on-balena-os/179421/18
- 投稿日:2021-05-16T12:36:41+09:00
Host 'IPアドレス' is not allowed to connect to this MySQL serverの対処
DockerfileにImageMagicをインストールする記述を入れてコンテナイメージをビルドしました。 そこでDocker-composeを再起動してリロードをしてみた所、以下のエラーが出てきてしまいました。 Host 'IPアドレス' is not allowed to connect to this MySQL server そこで色々と考えてみたのですが、原因はおそらくいままでDocker、Docker−composeを使ってきた時に出てきたキャッシュが影響してしまっているのではないかと考えました。 幸いdocker-compose は起動することができていたので、以下のコマンドをやってみました。 docker-compose down --rmi all --volumes --remove-orphans というコマンドをやってみて、コンテナイメージとコンテナとネットワークなどをすべて削除しました。 そして、もう一度 docker-compose build をしてみました。 そうしたら無事起動しました。 キャッシュが影響することってよくあるんですね。 知らなかったです。 指摘や間違っているところがありましたらご指摘お願いします。 出典
- 投稿日:2021-05-16T11:37:24+09:00
データベースを設計する前に!
データベースを設計する前に データベースは多くの場合、アプリケーション本体よりも長く付き合っていくものになります。(開発している段階から使用する+他のアプリケーションでもそのデータベースを使う可能性があるため) 適当な名前をつけたり、一貫性のない名前の付け方をすると、読みづらくなるだけではなくトラブルの温床になります。自分だけしか利用しない場合であっても、以下の点を最低限考慮して設計すると良いでしょう。 予約語 データベースのテーブル名やカラム名などを決める際にまず考えなくてはいけないのは、使用したい言葉が予約語にないものかどうかを確認をすることです。予約語にその単語がある場合、SQLコマンドが正常に動作しない場合があります。 例えば、PHPだと使用するmigrationやseedingをartisanコマンドで実行した場合には、うまくいくけれど、その時発行されるSQL文を直接コンソールから入力すると予約語のエラーになるなどして、トラブルの原因特定が難しくなります。そのため、設計の段階から予約語は使わないように心がけましょう。 実際に使ってしまった予約語 column order こちらでMySQL公式サイトから予約語の確認ができます ページ内検索をかけて確認しましょう テーブル名は複数形 基本的にはテーブルに複数のカラムが入ることになるので、入る名称の複数形をつけることが一般的です。 例えばPHPでLaravelを使用しているとき、Modelクラスで定義したクラス名(単数形)とデータベース側のテーブル名の複数形が紐づくようになっているため、特別な理由がなければそのルールに従いましょう。 例)Model:Userクラス→Database:usersテーブル ※余談ですがLaravelの場合、「複数形」は英語のルールに則ったものになります。 例) box->boxes 単語と単語の間は「_」で区切ろう データベース内では大文字小文字が基本的に区別されません。 そのため、単語と単語の間は「_」で区切るような名前をつけると良いでしょう。この形式を「スネークケース」という。 例) user_id 外部キーを設定するときには、「テーブル名+_+id」で指定しよう テーブル同士に関連性を持たせる場合、外部キーなどを設定することがあります。多くの場合、外部キーの制約はPRIMARY KEYとなるidに対する制約をすることが多いでしょう。カラム名をみただけでどのテーブルの何カラムに対する外部キーなのかがわかるようにしましょう。 例) usersテーブルのidカラムに対する外部キーをuser_infoテーブルに設定する場合 usersテーブル user_infoテーブル id id account name password address users_id
- 投稿日:2021-05-16T11:37:24+09:00
データベースを設計する前に
データベースを設計する前に データベースは多くの場合、アプリケーション本体よりも長く付き合っていくものになります。(開発している段階から使用する+他のアプリケーションでもそのデータベースを使う可能性があるため) 適当な名前をつけたり、一貫性のない名前の付け方をすると、読みづらくなるだけではなくトラブルの温床になります。自分だけしか利用しない場合であっても、以下の点を最低限考慮して設計すると良いでしょう。 予約語 データベースのテーブル名やカラム名などを決める際にまず考えなくてはいけないのは、使用したい言葉が予約語にないものかどうかを確認をすることです。予約語にその単語がある場合、SQLコマンドが正常に動作しない場合があります。 例えば、PHPだと使用するmigrationやseedingをartisanコマンドで実行した場合には、うまくいくけれど、その時発行されるSQL文を直接コンソールから入力すると予約語のエラーになるなどして、トラブルの原因特定が難しくなります。そのため、設計の段階から予約語は使わないように心がけましょう。 実際に使ってしまった予約語 column order こちらでMySQL公式サイトから予約語の確認ができます ページ内検索をかけて確認しましょう テーブル名は複数形 基本的にはテーブルに複数のカラムが入ることになるので、入る名称の複数形をつけることが一般的です。 例えばPHPでLaravelを使用しているとき、Modelクラスで定義したクラス名(単数形)とデータベース側のテーブル名の複数形が紐づくようになっているため、特別な理由がなければそのルールに従いましょう。 例)Model:Userクラス→Database:usersテーブル ※余談ですがLaravelの場合、「複数形」は英語のルールに則ったものになります。 例) box->boxes 単語と単語の間は「_」で区切ろう データベース内では大文字小文字が基本的に区別されません。 そのため、単語と単語の間は「_」で区切るような名前をつけると良いでしょう。この形式を「スネークケース」という。 例) user_id 外部キーを設定するときには、「テーブル名+_+id」で指定しよう テーブル同士に関連性を持たせる場合、外部キーなどを設定することがあります。多くの場合、外部キーの制約はPRIMARY KEYとなるidに対する制約をすることが多いでしょう。カラム名をみただけでどのテーブルの何カラムに対する外部キーなのかがわかるようにしましょう。 例) usersテーブルのidカラムに対する外部キーをuser_infoテーブルに設定する場合 usersテーブル user_infoテーブル id id account name password address users_id
- 投稿日:2021-05-16T11:10:00+09:00
Dockerを嗜む(1)
経緯など そろそろ一回ぐらいDockerを嗜んでおこうと思っていろいろと整理してみた。 前提 コンテナの大枠はなんとなく知っている やりたいこと コンテナを作成して、AWS上でpythonの処理を定期実行させたい 知識の整理 いろいろと検索して調べたが、数年前のAWS Summitの講演/資料が概念を理解するのによかった。 【初級】AWS コンテナサービス入門 | AWS Summit Tokyo 2019 https://www.youtube.com/watch?v=L4bLDNRSYC8 https://pages.awscloud.com/rs/112-TZM-766/images/C3-01.pdf やってみる 環境 Windows10 home 0.もろもろセットアップ Windowsの場合 Docker Desktop for Windowsをインストール https://hub.docker.com/editions/community/docker-ce-desktop-windows Power Shellのバージョンを上げろと言ってくるかもしれないので、必要に応じてアップデート ※準備はこれでOK 以前はWindowsHomeでやろうと思ったらいろいろとめんどくさかった記憶があるのだが、WSL2がリリースされたのでこれでOKらしい。 確認:超シンプルなubuntuを使って確認してみる イメージを読み込む Power Shellを管理者モードで起動して以下を実行 docker pull ubuntu これでイメージがDLされる 実行(コンテナを起動してログイン) docker run -it ubuntu ※別の入り方。 Docker Desktopで起動させ、コンテナ名(コンテナ識別子)を確認して下記を実行(起動中のコンテナにログイン) docker exec -it -u root <コンテナ名> bash コンテナの削除 docker rm happy_stonebraker イメージの削除 docker rmi ubuntu これで消えているのが確認できるはず。 ただ、コンテナやイメージの削除についてはDocker Desktopから操作したほうがわかりやすいかもしれない。 ※また、Windows Homeを使用している場合は全部がきれいに消えているわけではないので、 別途きれいにしてあげないと容量が減ったままとなってしまう。 以下を参考に作業をするとちゃんと削除することができる https://www.curict.com/item/f4/f46da60.html このあと とりあえずこれでローカルでコンテナを作成することができたので、次回以降はいろいろと加工して自分がやりたい処理ができるコンテナを作成して、どこかで定期実行させよう
- 投稿日:2021-05-16T01:56:53+09:00
Windows10のDocker環境で Atom + Xdebug を動作させる
はじめに Xdebugを使いたいとずっとふわっと思ってて、過去に何回かチャレンジするもうまくいかず。。 最近やっとこ上手くいったのでまとめます。 自分もDocker初心者なので、Dockerファイルの内容についても色々調べつつ進めていたので、 同じように初心者の方へ参考になれば。 とりあえずうまくいった設定方法 典型的なLAMPの構成です。 Dokerfile # ベースのDockerイメージを指定:DockerHUBからイメージ[php]のタグ[7.1-apache]を指定 # https://hub.docker.com/ FROM php:7.1-apache # php設定ファイルを独自指定とするため上書き COPY ./php.ini /usr/local/etc/php/ # サーバー初期処理 # apt-get update : パッケージ情報の更新 # apt-get install : パッケージのインストール/更新 # git : GIT # unzip : ZIPの解凍 # libzip-dev : zip圧縮の基本ライブラリー # libicu-dev : Unicodeと他の文字コードとの間の変換をしてくれるライブラリ # libonig-dev : マルチバイト文字をサポートする正規表現関数のために必要なライブラリ # vim : テキストエディタ # locales : ロケール(言語と地域)設定 # locale-gen ja_JP.UTF-8 : # ロケールを追加 # localedef -f UTF-8 -i ja_JP ja_JP : # ロケール環境の定義 # ここからインストール完了後のゴミデータ削除処理 # apt-get clean : /var/cache/apt/archivesにキャッシュされたパッケージファイルを削除する # rm -rf /var/lib/apt/lists/* : /var/cache/apt/list にキャッシュされている全てのパッケージリストを削除 # docker-php-ext-install : PHPエクステンションインストール # intl : phpの国際化用拡張モジュール # pdo_mysql : PDO MySQL 拡張モジュール # mysqli : MySQLi拡張モジュール # zip : zip 拡張モジュール # bcmath : bcmath 拡張モジュール RUN apt-get update && \ apt-get -y install git unzip libzip-dev libicu-dev libonig-dev vim && \ apt-get -y install locales && \ locale-gen ja_JP.UTF-8 && \ localedef -f UTF-8 -i ja_JP ja_JP && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ docker-php-ext-install intl pdo_mysql mysqli zip bcmath # ENV <name> <value>でコンテナ内で使える環境変数を指定 ENV DOCUMENT_ROOT=/var/www/html/ # linuxの言語にUTF-8を指定 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL=ja_JP.UTF-8 # UTC(協定世界時)→JST(日本時間)に変更 RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime # composer 2.0 のインストール COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer # ログディレクトリとwebルートディレクトリ作成 RUN mkdir /var/www/log /var/www/session \ && chown -R www-data:www-data /var/www/log/ /var/www/session/ \ && mkdir ${DOCUMENT_ROOT} # DockerFIleのワークディレクトリを指定 # これ以降の処理のパス指定はここ基準で設定される WORKDIR ${DOCUMENT_ROOT} # 開発用にxdebugインストール RUN pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug # debian 系の apache で mod_rewrite を有効化する RUN a2enmod rewrite # apacheの設定ファイルにhtaccessの許可設定を指定 COPY ./000-default.conf /etc/apache2/sites-available/ # 外部公開するポート EXPOSE 80 Xdebugは、Xdebugがインストールされているサーバー側からローカル側へDebug用のデータを飛ばすので 9000番は外部公開不要です。(その辺の動きも理解出来てなく、色々ハマっていました;) 000-default.conf <VirtualHost *:80> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName # specifies what hostname must appear in the request's Host: header to # match this virtual host. For the default virtual host (this file) this # value is not decisive as it is used as a last resort host regardless. # However, you must set it for any further virtual host explicitly. #ServerName www.example.com ServerAdmin webmaster@localhost DocumentRoot /var/www/html # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. # It is also possible to configure the loglevel for particular # modules, e.g. #LogLevel info ssl:warn ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to # include a line for only one particular virtual host. For example the # following line enables the CGI configuration for this host only # after it has been globally disabled with "a2disconf". #Include conf-available/serve-cgi-bin.conf <Directory /var/www/html> Options Indexes FollowSymLinks MultiViews AllowOverride All Require all granted </Directory> </VirtualHost> php.ini [Core] display_errors = On error_reporting = E_ALL error_log = /var/www/log/apache2/error.log log_errors = On [Date] date.timezone = 'Asia/Tokyo' [mbstring] mbstring.language = Japanese mbstring.internal_encoding = auto mbstring.http_input = auto mbstring.http_output = auto mbsting.encoding_translation = Off mbstring.detect_order = auto [xdebug] xdebug.remote_enable=1 xdebug.remote_host=host.docker.internal xdebug.remote_port=9000 xdebug.remote_handler=dbgp xdebug.remote_mode=req xdebug.remote_autostart=1 docker-compose.yml version: '3.7' services: app: container_name: web build: . image: app_server:lastest ports: - '8080:80' depends_on: - db volumes: - ./html:/var/www/html - ./log:/var/www/log privileged: true restart: always db: container_name: db image: mysql:5.7.12 ports: - "33306:3306" command: - --sql-mode= volumes: # 初期データ流し込み指定フォルダ - ./docker-db/initdb.d:/docker-entrypoint-initdb.d # Dbデータ永続化するときにマウントするvolume - db:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root restart: always # DBはトランザクションデータのため、外部データボリュームに永続化 volumes: db: appのポート変換も、app側からローカル側にデータを飛ばすので ports: - '9000:9000' のような指定は不要です。 Xdebugの設定ポイント Xdebugのインストール Dokerfile # 開発用にxdebugインストール RUN pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug phpinfoで、Xdebugの項目があればインストールが成功しています。 php.iniでxdebugのパラメータ設定 xdebug.remote_hostはhost.docker.internalでいけるみたいな記事もありましたが、 Windows環境だからなのか上手くいかず。作業端末のIPアドレスを指定してやるとうまく通りました。 動きを理解して改めて「host.docker.internal」設定してみたらちゃんと通りました。 php.ini [xdebug] xdebug.remote_enable=1 xdebug.remote_host=host.docker.internal xdebug.remote_port=9000 xdebug.remote_handler=dbgp xdebug.remote_mode=req xdebug.remote_autostart=1 Atomの設定 php-debugの設定 動作確認 breakpointを付けて、 Webサーバーにアクセスして、 デバッグが始まれば成功です。