😊
Dagger Node.js SDKを使ってNuxt3をEC2にデプロイ
前提
- SSMでEC2にログインできること
Daggerとは?
Dagger is a programmable CI/CD engine that runs your pipelines in containers.
(公式から引用)
CI/CDを好きな言語で書いて、コンテナで実行できるということだと思います。
各バージョン
$ node -v
v18.17.0
package.json
// ...
"@dagger.io/dagger": "^0.6.4",
// ...
実装
Nuxt3アプリのビルド -> デプロイを実装しています。
環境変数は適宜設定してください。
公式のGet Startedをベースに必要な処理を追加しました。公式のドキュメントが充実しているので、だいたいはここを見ればわかります。
build.mts
import Client, { connect } from '@dagger.io/dagger'
connect(
async(client: Client) => {
// ビルド
const hostSrcDir = client.host().directory('.', { exclude: ['node_modules/'] })
const builder = client.container().from('node:18.14-slim')
.pipeline('build')
.withDirectory('/src', hostSrcDir) // ソースをマウント
.withWorkdir('/src')
.withExec(['yarn', 'set', 'version', 'berry'])// yarnのバージョンを上げる なくても動くはず
.withExec(['yarn', 'install'])
.withExec(['yarn', 'build'])
await builder.sync()
// デプロイ用の変数を環境変数から取得
const serverPrivateKey = process.env.SERVER_PRIVATE_KEY || ''
const ec2User = process.env.EC2_USER || ''
const ec2Server = process.env.EC2_SERVER || ''
const awsAccessKeyId = client.setSecret('AWS_ACCESS_KEY_ID', process.env.AWS_ACCESS_KEY_ID || '')
const awsSecretAccessKey = client.setSecret('AWS_SECRET_ACCESS_KEY', process.env.AWS_SECRET_ACCESS_KEY || '')
const awsDefaultRegion = client.setSecret('AWS_DEFAULT_REGION', process.env.AWS_DEFAULT_REGION || '')
// デプロイ
// nodeのイメージである必要はないが、ビルド用コンテナと違うイメージを使うとダウンロードが発生するので揃えています
const deployer = client.container().from('node:18.14-slim')
.pipeline('deploy')
// ソースを配置
.withDirectory('/src/.output', builder.directory('/src/.output'))
.withFile('/src/pm2.config.js', client.host().file('pm2.config.js'))
// 必要パッケージのインストール
.withExec(['apt-get', 'update'])
.withExec(['apt-get', '-y', 'install', 'curl', 'unzip', 'openssh-client', 'rsync'])
// AWS CLIのインストール・設定
.withExec(['curl', 'https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip', '-o', 'awscliv2.zip'])
.withExec(['unzip', 'awscliv2.zip'])
.withExec(['./aws/install'])
.withSecretVariable('AWS_ACCESS_KEY_ID', awsAccessKeyId)
.withSecretVariable('AWS_SECRET_ACCESS_KEY', awsSecretAccessKey)
.withSecretVariable('AWS_DEFAULT_REGION', awsDefaultRegion)
// AWS CLIのSession Managerプラグインのインストール
.withExec(['curl', 'https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb', '-o', 'session-manager-plugin.deb'])
.withExec(['dpkg', '-i', 'session-manager-plugin.deb'])
// SSH設定追加
// ※ssh -i で秘密鍵を指定する方法だと動かなかったので、鍵のパスをssh_configに記述しています
.withNewFile('/etc/ssh/ssh_config', { contents: 'host i-*\n\tProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters \'portNumber=%p\'"\n\tStrictHostKeyChecking no\n\tIdentityFile /tmp/private.key' })
.withNewFile('/tmp/private.key', {
contents: serverPrivateKey,
permissions: 0o0600
})
// デプロイ
await deployer
// ソースを更新
.withExec(['rsync', '-ae', 'ssh', '/src/', `${ec2User}@${ec2Server}:app_dir/`])
// pm2サーバーを起動
.withExec(['ssh', `${ec2User}@${ec2Server}`, 'pm2', 'restart', "'app_name'"])
.sync()
},
{ LogOutput: process.stderr }
)
実行
$ node --loader ts-node/esm ./build.mts
問題点
- デプロイの度にaws cliなどをインストールするので遅い
- デプロイ用イメージを作ってDocker HubなりGitLab Container Registryなりに登録すると解消できると思う(イメージの公開もDaggerでできるっぽい)
参考
Discussion