ゲノムブラウザ JBrowse2 を CloudFront + S3 で Web 公開してみた
ゲノムブラウザの JBrowse を Web 公開するときに Web サーバー(Apache, Nginx)が必要なのか調べていました。 すると、静的サイトなので Amazon S3 でも動作すると公式ガイドに書いてあります。ということで試してみました。
JBrowse doesn't strictly need Apache or nginx, it is "static site compatible" meaning it uses no server code and can run on any static website hosting. For example, you can upload the jbrowse folder that we prepared here in /var/www/html/jbrowse2 to Amazon S3, and it will work there too. See the FAQ for what webserver do I need for more info. 引用: JBrowse 2 combined guide | JBrowse
ところで S3 で公開するとなにが嬉しいの?と言われますと、サーバーに比べると格段に維持費が安いのも嬉しいですけど、なにより Web サーバーの運用・管理をしなくて済むのが嬉しいのではないでしょうか。今回は定番の構成で CDN のサービスとセットで環境構築します。
構成図
CloudFront(CDN)+ S3 構成にカスタムドメインでアクセスできる環境を Cloudformation で作成します。
CloudFront と S3 の準備
ゲノムブラウザを Web 公開するための静的サイトを構築します。あとで中身(ファイル)を入れて静的サイトが完成します。
前提
- Route53 にドメイン名の登録済み
- CloudFront で使用する証明書をバージニア北部(us-east-1)リージョンに登録済み
テンプレート
CloudFront のログは180日保存で自動削除のライフサイクルルールが設定してあります。ログ保持期限ポリシーがある場合はお気をつけください。
bigmuramura/cfn-cloudfront-s3にも置いてあります。
折りたたみ
AWSTemplateFormatVersion: "2010-09-09" Description: Cloudfront and S3 Parameters: ProjectName: Description: Project Name Type: String Default: unnamed Environment: Description: Environment Type: String Default: dev AllowedValues: - prod - dev S3BucketName: Description: Bucket name for static site Type: String AliasName: Description: Alias for CloudFront Type: String HostedZoneId: Description: Route53 Host Zone ID Type: String CertificateId: Description: ACM Certificate ID must be us-east-1 region Type: String Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Common Settings Parameters: - ProjectName - Environment - Label: default: SSL Settings Parameters: - AliasName - HostedZoneId - CertificateId Resources: # ------------------------------------------------------------------------------------ # # S3 # ------------------------------------------------------------------------------------ # # Static site bucket S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId} OwnershipControls: Rules: - ObjectOwnership: "BucketOwnerEnforced" PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" BucketKeyEnabled: false LifecycleConfiguration: Rules: - Id: AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload: DaysAfterInitiation: 7 Status: "Enabled" - Id: NoncurrentVersionExpiration NoncurrentVersionExpiration: NewerNoncurrentVersions: 3 NoncurrentDays: 1 Status: Enabled # Bucket Policy for CloudFront BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3Bucket PolicyDocument: Statement: - Action: s3:GetObject Effect: Allow Resource: !Sub arn:aws:s3:::${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}/* Principal: AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity} # ------------------------------------------------------------------------------------ # # CloudFront # ------------------------------------------------------------------------------------ # CloudFrontDistribution: Type: "AWS::CloudFront::Distribution" Properties: DistributionConfig: PriceClass: PriceClass_All Origins: - DomainName: !Sub ${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}.s3.${AWS::Region}.amazonaws.com Id: !Sub "S3origin-${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}" S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}" DefaultRootObject: index.html DefaultCacheBehavior: TargetOriginId: !Sub "S3origin-${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}" Compress: true ViewerProtocolPolicy: redirect-to-https CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD ForwardedValues: Cookies: Forward: none QueryString: false Logging: Bucket: !GetAtt S3BucketLogs.DomainName IncludeCookies: false Aliases: - !Ref AliasName ViewerCertificate: SslSupportMethod: sni-only MinimumProtocolVersion: TLSv1.2_2021 AcmCertificateArn: !Sub "arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/${CertificateId}" HttpVersion: http2 IPV6Enabled: true Enabled: true # OAI CloudFrontOriginAccessIdentity: Type: AWS::CloudFront::CloudFrontOriginAccessIdentity Properties: CloudFrontOriginAccessIdentityConfig: Comment: Unique Domain Hosting Environment # CloudFront log bucket S3BucketLogs: Type: AWS::S3::Bucket DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: BucketName: !Sub ${ProjectName}-${Environment}-${S3BucketName}-cloudfrontlogs-${AWS::AccountId} OwnershipControls: Rules: - ObjectOwnership: "ObjectWriter" PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" BucketKeyEnabled: false LifecycleConfiguration: Rules: - Id: AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload: DaysAfterInitiation: 7 Status: "Enabled" - Id: CurrentVersionExpiration ExpirationInDays: 180 Status: "Enabled" - Id: NoncurrentVersionExpiration NoncurrentVersionExpiration: NoncurrentDays: 30 Status: "Enabled" # Alias Record Route53RecordSet: Type: AWS::Route53::RecordSet Properties: Name: !Sub ${AliasName} HostedZoneId: !Sub ${HostedZoneId} Type: A AliasTarget: DNSName: !GetAtt CloudFrontDistribution.DomainName HostedZoneId: Z2FDTNDATAQYW2 # fixed
パラメータで前提事項であった事前作成済みリソースのIDを入力します。
- ホストゾーンID
- Route53よりドメインを確認
- 証明書ID
- バージニア北部(us-east-1)で発行した証明書を確認
CloudFront の他、S3 バケットが2つ作成されます。上が静的サイトとして CloudFront を通して Web 公開されるバケットです。下は CloudFront のアクセスログ保存用のバケットです。後ほど上のバケットに Jbrowse2 のファイルをアップロードします。
JBrowse のファイル準備
前回 JBrowse ローカル実行環境を作成しましたので、以下のリンクを参考にjbrowse2
フォルダを作成し静的サイトに必要ファイルを生成します。
最終的に /var/www/html
配下に作成されるjbrowse2
フォルダを S3 にアップロードして Web 公開します。
jbrowse2 フォルダ作成
/var/www/html
配下にjbrowse
フォルダ作成する予定のためローカル PC のディレクトリをマウントします。これでコンテナ内の JBrowse CLI でセットアップする初期ファイルを永続化できます。ここではマウントするディレクトリは/Users/ohmura.yasutaka/work/jbrowse/vol
を例にすすめていきます。
$ docker run -it -p 3000:3000 -v /Users/ohmura.yasutaka/work/jbrowse/vol:/var/www/html jbrowse2:v1 bash
前回のローカル環境構築手順と同様にショウジョウバエのリファレンスゲノムをサンプルに使用します。
# jbrowse create /var/www/html/jbrowse2 # cd /tmp # wget https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/001/215/GCF_000001215.4_Release_6_plus_ISO1_MT/GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna.gz # gunzip GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna.gz # samtools faidx GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna # jbrowse add-assembly GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna --out /var/www/html/jbrowse2 --load copy
コンテナにマウントしたローカルディレクトリ(vol
配下)に必要なjbrowse2
フォルダが作成・保存されました。
$ pwd /Users/ohmura.yasutaka/work/jbrowse/vol $ tree -L 2 . └── jbrowse2 ├── GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna ├── GCF_000001215.4_Release_6_plus_ISO1_MT_genomic.fna.fai ├── asset-manifest.json ├── config.json ├── favicon.ico ├── index.html ├── manifest.json ├── robots.txt ├── static ├── test_data └── version.txt
ファイルをアップロード
Cloudformation で作成した静的サイト用の S3 バケットに jbrowse2
配下のファイルをコピーします。オリジナルの TOP ページを作成する場合は index.html
を自作してアップロードし、jbrowse2
のファイル類はパスを切ってアップロードしてください。ここでは Jbrowse2 で必要なファイルをシンプルにアップロードします。
.fna
ファイルの容量はそこそこのサイズがあると思いますので aws s3 sync
で転送すると効率が良いです。
$ aws s3 sync ~/work/jbrowse/vol/jbrowse2/ s3://sample-dev-jbrowse-123456789012
S3 バケットを確認するとファイルがアップロードされています。
index.html
について触れたのは CloudFront の設定にあるデフォルトルートオブジェクトで指定済みだったためです。CloudFront のテンプレートに書き込んでいるため、必要に応じてファイル名に変更してください。
Web アクセスしてみる
https://独自ドメイン
でアクセスできます。
CloudFront + S3 バケットで構成した環境でもゲノムブラウザを操作できますね。
リロードするとキャッシュにヒットしていることから CloudFront からの配信であることも確認できます。
補足 アクセス制限
S3 へ直接アクセスはできない構成にしてあります。CloudFront でアクセス制限をかければ公開範囲を制限することもできます。
グローバル IP 制限
Basic 認証
おわりに
バイオインフォマティクスで使われるツールのドキュメントにも AWS の用語が登場する時代なんだという発見がありました。と同時に第一線の研究者が S3 で静的サイトを構築できるかというとまた話は別かなとも思いました。研究者とクラウドのインフラをいい感じに取り持てる人は研究現場で重宝されそうですね。