EC2でdocker起動

今日は仕事しないつもりなんですけどね。はい。

てきとーにさくっとEC2でRails + MySQL + phpMyAdminのdocker-compose起動したい時のメモ
まぁコンテナが使うポートをセキュリティグループで許可する以外どんな構成でもえーと思うで。

おもむろにEC2のインスタンスを起動しましょう。
パブリックサブネットにパブリックIP自動でセキュリティグループは22, 80, 8080のインバウンドを開けておきましょう。
で、ユーザーデータにこれをコピペ
よく使いそうなもんもてきとーにインストールしておきましょ。

#!/bin/bash
sudo yum update -y
sudo yum install -y git docker make vim curl
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -a -G docker ec2-user
sudo mkdir -p /usr/local/lib/docker/cli-plugins
VER=2.5.1
sudo curl \
-L https://github.com/docker/compose/releases/download/v${VER}/docker-compose-$(uname -s)-$(uname -m) \
-o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose

起動したらsshで入って、git cloneなり、docker-compose buildなり、docker-compose upなり、ご自由に。

// -------------

宣伝

最近はPoC開発が好きです。
もちろん大規模・高トラフィックも安定に自信ありますけども。
お仕事ください。

最近よく使うものたち。


Flutter - iOS / Android向け入門3 - json_annotation編

第3回です。

オブジェクト > jsonやらjson > オブジェクトやらしたいよね?
いい感じのORMがなくて、一旦無難にこれ。

json_annotation | Dart Package

おもむろにこんな定義を用意しましょう。

import 'package:json_annotation/json_annotation.dart';

part 'sample.g.dart';

@JsonSerializable()
class Sample {
  final String hoge;
  const Sample(this.hoge);

  factory Sample.fromJson(Map<String, dynamic> json) =>
      _$SampleFromJson(json);
  Map<String, dynamic> toJson() => _$SampleToJson(this);
}

そして実行

`flutter pub run build_runner build`

profile.g.dartっていうのができるよ。
あとは普通にjsonEncodeだったり、jsonDecodeだったりに使うだけ。


// -------------

宣伝

最近はPoC開発が好きです。
もちろん大規模・高トラフィックも安定に自信ありますけども。
お仕事ください。

最近よく使うものたち。


Flutter - iOS / Android向け入門2 - FirebaseMessaging導入編

バックナンバーはこちら

第1回: Flutter - iOS / Android向け入門1 - ふるすたっくえんじにあの日記


はい、第2回です。

  • 設定はこれだけですね。特に詰まることもないかと。

Flutter アプリに Firebase を追加する

と思ったら詰まりました。
`brew upgrade cocoapods`したら直りました。

  • main.dartのmainメソッドを編集
void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await FirebaseMessaging.instance.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  runApp(const MyApp());
}

トークン確認したければ

final token = await FirebaseMessaging.instance.getToken();

`ios/Runner.xcworkspace`を開いて、Runner.xcodeproj > TARGETS > Runner > Signing & Capabilities > + Capabilityで

  • Push Notifications
  • Background Modes > Remote notifications

を。

// -------------

宣伝

最近はPoC開発が好きです。
もちろん大規模・高トラフィックも安定に自信ありますけども。
お仕事ください。

最近よく使うものたち。


Flutter - iOS / Android向け入門1 - プロジェクトの初期設定編

2年半ぶりの更新です。
放置してても地味にPVあるのが技術ブログのいいとこですね。情報古いと思うけどね。
この2年半の間に一体どれだけの技術を覚えたことでしょう。
ということでちょいちょい記事書いていこうかなと。

最近よく使うものたち書いておきますね。

最近はPoC開発が好きです。
もちろん大規模・高トラフィックも安定に自信ありますけども。
お仕事ください。

というわけで本編。

環境構築

  • Hombrew

これみてね。
・ターミナルでやること > # homebrew と # FVM
VSCode > Flutter
・~/.zprofile > Flutter
が必要です。
Mac初期設定 for フルスタックエンジニア - ふるすたっくえんじにあの日記

  • FVM

もし先にFlutterインストールしてたら削除しましょう。
Installation | Flutter Version Management

FlutterとDartのextensionを入れましょう。
Dart Code - Dart & Flutter support for Visual Studio Code

  • Create Project

こちら。
Your first Flutter app  |  Google Codelabs

プロジェクトのセットアップ

  • FVM

プロジェクト直下に`.fvm/config.json`を作りましょう。
versionは`fvm release`で、stableなやつを。
後でflutter pubなんちゃら実行する時にインストールするか聞いてくれるからここでは何もいらないよ。

{
  "flutterSdkVersion": "3.7.8",
  "flavors": {}
}

.gitignoreに以下を追記しましょう

.fvm/flutter_sdk
  • localization

pubspeck.yamlに以下追記

dependencies:
  ...
  flutter_localizations:
    sdk: flutter
  • packageインストール

おもむろに以下をインストールしていきましょう。
今回使うのはflutter_native_splashだけです。
今回はあんまり関係ないけど、後々使うやつも入れておきましょう。
たぶん大抵のアプリで使う。
そのうち一つずつ説明するよ。たぶん。

flutter pub add --dev build_runner
flutter pub add --dev flutter_native_splash
flutter pub add --dev json_serializable
flutter pub add cached_network_image
flutter pub add collection
flutter pub add event_bus
flutter pub add firebase_core
flutter pub add firebase_messaging
flutter pub add firebase_remote_config
flutter pub add fk_user_agent
flutter pub add flutter_local_notifications
flutter pub add http
flutter pub add intl
flutter pub add json_annotation
flutter pub add package_info
flutter pub add path_provider
flutter pub add pretty_http_logger
flutter pub add rxdart_ext
flutter pub add rxdart
flutter pub add share
flutter pub add shared_preferences
flutter pub add unique_identifier
flutter pub add url_launcher
flutter pub add webview_flutter
  • assets配置用フォルダの設定

pubspec.yamlに以下追記

flutter:
  ...
  assets:
    - assets/images/
    - assets/images/ios/
    - assets/images/android/
  • アプリアイコンの設定

普通にios / androidフォルダの中をXcode / Android Studioで開いて設定するのが早い

  • スプラッシュ画面の差し替え

これはpackage使ったほうが楽
pub.dev

pubspec.yamlに以下追記

flutter_native_splash:
  color: "#e1f5fe"
  image: assets/images/splash.png
  color_dark: "#042a49"
  image_dark: assets/images/splash_dark.png
  android_12:
    image: assets/images/android/splash_12.png
    color: "#42a5f5"
    icon_background_color: "#eeeeee"
  fullscreen: true

imageで指定した場所に画像を置いて実行

flutter pub run flutter_native_splash:create
  • iOS設定
  • ios/Podfileに追記
platform :ios, '15.0'
  • ios/Runner.xcodeproj/project.pbxprojを修正

IPHONEOS_DEPLOYMENT_TARGETを15.0に。

ios/Podfile.lock消してios配下でpod installはしたほうがいいかもしれない

今日はここまで


【AWS】固定IP用のVPNを構築する-初心者向け

はい。久しぶり。いつぶりでしょ。
PVあがりそうなタグつけておきますね。
#在宅ワーク #リモートワーク #ワーケーション #コロナ対策 #出社自粛
#SSO #AWS #AWS VPN Client #VPC

最近いくつか固定IPなVPN構築の要望あって、自社のVPNおったてつつ手順をまとめておきますよ。
初心者向けっていくつか見たけど、全然初心者向けじゃなかったよ。CIDRなんて初心者わからへんやろ。
そして自社のシステムが一番イケてるのは内緒。一番最後にやる&何の制約もなくて自由度が一番高いから当たり前っちゃ当たり前なんだけど。
そのうちIdPはKeycloakに移行予定。

  • Oktaの設定とIAM IDプロバイダーの作成

めんどくなったのでこちらを参考に
https://dev.classmethod.jp/articles/clientvpn_saml_okta/

  • 証明書作成とインポート

gitコマンドがターミナルから使える前提。
以下のコマンドをさくっと実行しましょう。

```
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa build-server-full vpn.static.ip.server nopass
```

https://ap-northeast-1.console.aws.amazon.com/acm/home?region=ap-northeast-1#/importwizard/
証明書本文: pki/issued/vpn.static.ip.server.crtの-----BEGIN CERTIFICATE-----から-----END CERTIFICATE-----まで
証明書のプライベートキー: pki/private/vpn.static.ip.server.key
証明書チェーン: pki/ca.crt
の内容をコピペしましょう。

  • Elastic IP取得

https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#Addresses:
ここから「Elastic IP アドレスの割り当て」
AmazonIPv4 アドレスプール」
「割り当て」
これでできたIPアドレスグローバルIPになります。

https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#wizardSelector:
ここから「パブリックとプライベートサブネットを持つ VPC」を作成
VPC名: 任意
アベイラビリティーゾーン: パブリック/プライベートで同じに
パブリック/プライベートサブネット名: 指定
Elastic IP 割り当て ID: さっき指定したやつを選択

  • クライアント VPN エンドポイントの作成

https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#CreateClientVpnEndpoint:
ここから
名前タグ: 任意
説明: 任意
クライアントIPv4 CIDR: 10.10.0.0/16
サーバー証明書 ARN: さっき作った証明書
認証オプション: ユーザーベースの認証を使用 - 統合認証
SAML プロバイダー ARN: さっき作ったやつ

  • 関連付けなどなど

作ったクライアント VPN エンドポイント - 関連付け: VPCは作ったVPC、サブネットはプライベートのほうを設定
作ったクライアント VPN エンドポイント - 承認
 アクセスを有効にする送信先ネットワーク: 0.0.0.0/0
 すべてのユーザーにアクセスを許可する
作ったクライアント VPN エンドポイント - ルートテーブル
 ルート送信先: 0.0.0.0/0
 ターゲット VPC サブネット ID: プライベートのほう

  • 設定ファイルのダウンロード

作ったクライアント VPN エンドポイントを選択して「クライアント設定のダウンロード」

  • 接続

AWS Client VPN Download | Amazon Web Services
ここからダウンロードしてインストール
開いたらファイル - プロファイルを管理 - プロファイルを追加でさっき作ったファイルを指定
で、接続

いじょ。



Github PR作成 from GAS

昔作ったけど、気に食わなかった&他社で作ったから勝手に使えないので自社用に作り直したぉ。
ごにょごにょしたらスプレッドシートから作れるね!

おもむろにこんなのを用意しましょう。
github_repos_api.gs

var GithubReposAPI = function(repositoryOwner, repository, accessToken) {
  this.repositoryOwner = repositoryOwner;
  this.repository = repository;
  this.accessToken = accessToken;
};
// PRとブランチをセットで作成
GithubReposAPI.prototype.createPullRequestWithBranch = function(sourceBranchName, newBranchName, authorName, authorEmail, title, body, draft) {
  this.createBranch(sourceBranchName, newBranchName, title, authorName, authorEmail);
  return this.createPullRequest(title, body, newBranchName, sourceBranchName, draft);
}

// ブランチ作成
GithubReposAPI.prototype.createBranch = function(sourceBranchName, newBranchName, message, authorName, authorEmail) {
  const commit = this.createCommit(sourceBranchName, message, authorName, authorEmail);
  return this.execute(
    'POST',
    '/git/refs',
    {
      'ref': 'refs/heads/' + newBranchName,
      'sha': commit.sha
    }
  );
};
GithubReposAPI.prototype.createCommit = function(branchName, message, authorName, authorEmail) {
  const branch = this.fetchBranch(branchName);
  return this.execute(
    'POST',
    '/git/commits',
    {
      'message': message,
      'author': {
        'name': authorName,
        'email': authorEmail
      },
      'parents': [
        branch.commit.sha
      ],
      'tree': branch.commit.commit.tree.sha
    });
};
GithubReposAPI.prototype.fetchBranch = function(branchName) {
  return this.execute('GET', '/branches/' + branchName);
};

// PR作成
GithubReposAPI.prototype.createPullRequest = function(title, body, head, base, draft) {
  return this.execute(
    'POST',
    '/pulls',
    {
      'title': title,
      'body': body,
      'head': head,
      'base': base,
      'draft': draft
    }
  );
};

GithubReposAPI.prototype.execute = function(method, api, payload) {
  const url = 'https://api.github.com/repos/' + this.repositoryOwner + '/' + this.repository + api;
  const param = this.generateParam(method, payload);
  return fetch(url, param);
};
GithubReposAPI.prototype.generateParam = function(method, payload) {
  if (payload) {
    return {
      'method': method,
      'Content-Type': 'application/json',
      'muteHttpExceptions': true,
      'payload': JSON.stringify(payload),
      'headers': {
        'Authorization': 'token ' + this.accessToken
      }
    };
  }
  return {
    'method': method,
    'Content-Type': 'application/json',
    'muteHttpExceptions': true,
    'headers': {
      'Authorization': 'token ' + this.accessToken
    }
  };
};

function fetch(url, param) {
  Logger.log('[Request]---------------------------\n' + url + '\n' + JSON.stringify(param));
  var ret = JSON.parse(UrlFetchApp.fetch(url, param));
  Logger.log('[Response]---------------------------\n' + JSON.stringify(ret));
  return ret;
}


使い方

const api = new GithubReposAPI(
  'arrvis', // organization or username
  'test-repository', // リポジトリ名
  'XXXXXXXX' // Personal Access Token
);
api.createPullRequestWithBranch(
  'master', // 元ブランチ
  'feature/hoge', // 新しく作るブランチ名
  'Yutaka Izumaru', // author名
  'y.izumaru@arrvis.com', // authorメアド,
  'PRタイトル',
  'PR本文',
  false // draftかどうか
);


【iOS】GoogleService-Info.plistを環境別に分ける

ひさびさに書く

devdevdev.hatenablog.com

ここらへんが終わってること前提。まぁ2018年版なんでちょっと古いんですけどね。
TARGETS→Build Settings
らへんができてればおっけかと

$PROJECT_DIR/googleとか作って以下のファイルをぶちこみましょう

  • 本番用:GoogleService-Info.plist
  • ステージング用:GoogleService-Info.staging.plist
  • 開発用:GoogleService-Info.dev.plist

TARGETS→Build PhasesでNew Run Script Phaseして以下の内容を書きましょう

cp $PROJECT_DIR/google/GoogleService-Info$ConfigurationName.plist ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist

いじょー