@@ -22,19 +22,18 @@ Create file `Dockerfile` in `myadmin`:
22
22
23
23
``` Dockerfile title="./myadmin/Dockerfile"
24
24
# use the same node version which you used during dev
25
- FROM node:20 -alpine
25
+ FROM node:22 -alpine
26
26
WORKDIR /code/
27
27
ADD package.json package-lock.json /code/
28
28
RUN npm ci
29
29
ADD . /code/
30
30
RUN --mount=type=cache,target=/tmp npx tsx bundleNow.ts
31
- CMD ["npm " , "run " , "startLive " ]
31
+ CMD ["sh " , "-c " , "npm run migrate:prod && npm run prod " ]
32
32
```
33
33
34
-
35
34
## Step 2 - compose.yml
36
35
37
- create folder ` deploy ` and create file ` compose.yml ` inside:
36
+ Create folder ` deploy ` and create file ` compose.yml ` inside:
38
37
39
38
``` yml title="deploy/compose.yml"
40
39
@@ -51,10 +50,10 @@ services:
51
50
- " /var/run/docker.sock:/var/run/docker.sock:ro"
52
51
53
52
myadmin :
54
- build : ./myadmin
53
+ build : .. /myadmin
55
54
restart : always
56
55
env_file :
57
- - ./myadmin/.env
56
+ - ./myadmin/.env.secrets.prod
58
57
volumes :
59
58
- myadmin-db:/code/db
60
59
labels :
@@ -88,12 +87,12 @@ Create `deploy/.gitignore` file with next content:
88
87
*.tfstate.*
89
88
*.tfvars
90
89
tfplan
90
+ .env.secrets.prod
91
91
` ` `
92
92
93
93
# # Step 5 - Main terraform file main.tf
94
94
95
95
96
-
97
96
First of all install Terraform as described here [terraform installation](https://developer.hashicorp.com/terraform/install#linux).
98
97
99
98
@@ -102,7 +101,7 @@ Create file `main.tf` in `deploy` folder:
102
101
` ` ` hcl title="deploy/main.tf"
103
102
104
103
locals {
105
- app_name = "<your_app_name>"
104
+ app_name = "<your_app_name>" # replace with your app name
106
105
aws_region = "eu-central-1"
107
106
}
108
107
@@ -126,10 +125,10 @@ data "aws_vpc" "default" {
126
125
default = true
127
126
}
128
127
129
-
130
128
resource "aws_eip" "eip" {
131
129
domain = "vpc"
132
130
}
131
+
133
132
resource "aws_eip_association" "eip_assoc" {
134
133
instance_id = aws_instance.app_instance.id
135
134
allocation_id = aws_eip.eip.id
@@ -230,13 +229,34 @@ resource "aws_instance" "app_instance" {
230
229
systemctl start docker
231
230
systemctl enable docker
232
231
usermod -a -G docker ubuntu
232
+
233
+ echo "done" > /home/ubuntu/user_data_done
233
234
EOF
234
235
235
236
tags = {
236
237
Name = "${local.app_name}-instance"
237
238
}
238
239
}
239
240
241
+ resource "null_resource" "wait_for_user_data" {
242
+ provisioner "remote-exec" {
243
+ inline = [
244
+ "echo 'Waiting for EC2 software install to finish...'",
245
+ "while [ ! -f /home/ubuntu/user_data_done ]; do echo '...'; sleep 2; done",
246
+ "echo 'EC2 software install finished.'"
247
+ ]
248
+
249
+ connection {
250
+ type = "ssh"
251
+ user = "ubuntu"
252
+ private_key = file("./.keys/id_rsa")
253
+ host = aws_eip_association.eip_assoc.public_ip
254
+ }
255
+ }
256
+
257
+ depends_on = [aws_instance.app_instance]
258
+ }
259
+
240
260
resource "null_resource" "sync_files_and_run" {
241
261
# Use rsync to exclude node_modules, .git, db
242
262
provisioner "local-exec" {
@@ -262,16 +282,12 @@ resource "null_resource" "sync_files_and_run" {
262
282
# Run docker compose after files have been copied
263
283
provisioner "remote-exec" {
264
284
inline = [
265
- # fail bash specially and intentionally to stop the script on error
266
- "bash -c 'while ! command -v docker &> /dev/null; do echo \" Waiting for Docker to be installed...\" ; sleep 1; done'",
267
- "bash -c 'while ! docker info &> /dev/null; do echo \" Waiting for Docker to start...\" ; sleep 1; done'",
268
-
269
285
# please note that prune might destroy build cache and make build slower, however it releases disk space
270
286
"docker system prune -f",
271
287
# "docker buildx prune -f --filter 'type!=exec.cachemount'",
272
288
"cd /home/ubuntu/app/deploy",
273
289
# COMPOSE_FORCE_NO_TTY is needed to run docker compose in non-interactive mode and prevent stdout mess up
274
- "COMPOSE_FORCE_NO_TTY=1 docker compose -p app -f compose.yml up --build -d"
290
+ "COMPOSE_BAKE=true docker compose --progress=plain -p app -f compose.yml up --build -d"
275
291
]
276
292
277
293
connection {
@@ -287,7 +303,7 @@ resource "null_resource" "sync_files_and_run" {
287
303
always_run = timestamp()
288
304
}
289
305
290
- depends_on = [aws_instance.app_instance , aws_eip_association.eip_assoc]
306
+ depends_on = [null_resource.wait_for_user_data , aws_eip_association.eip_assoc]
291
307
}
292
308
293
309
@@ -310,6 +326,10 @@ resource "aws_s3_bucket_lifecycle_configuration" "terraform_state" {
310
326
status = "Enabled"
311
327
id = "Keep only the latest version of the state file"
312
328
329
+ filter {
330
+ prefix = ""
331
+ }
332
+
313
333
noncurrent_version_expiration {
314
334
noncurrent_days = 30
315
335
}
@@ -333,8 +353,6 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state"
333
353
}
334
354
}
335
355
}
336
-
337
-
338
356
` ` `
339
357
340
358
> 👆 Replace `<your_app_name>` with your app name (no spaces, only underscores or letters)
@@ -424,6 +442,11 @@ jobs:
424
442
with:
425
443
terraform_version: 1.10.1
426
444
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
445
+ - name: Prepare env
446
+ run: |
447
+ echo "ADMINFORTH_SECRET=$VAULT_ADMINFORTH_SECRET" > deploy/.env.secrets.prod
448
+ env:
449
+ VAULT_ADMINFORTH_SECRET: ${{ secrets.VAULT_ADMINFORTH_SECRET }}
427
450
- name: Start building
428
451
env:
429
452
VAULT_AWS_ACCESS_KEY_ID: ${{ secrets.VAULT_AWS_ACCESS_KEY_ID }}
@@ -477,6 +500,6 @@ Go to your GitHub repository, then `Settings` -> `Secrets` -> `New repository se
477
500
- ` VAULT_AWS_SECRET_ACCESS_KEY` - your AWS secret key
478
501
- ` VAULT_SSH_PRIVATE_KEY` - make `cat ~/.ssh/id_rsa` and paste to GitHub secrets
479
502
- ` VAULT_SSH_PUBLIC_KEY` - make `cat ~/.ssh/id_rsa.pub` and paste to GitHub secrets
480
-
503
+ - ` VAULT_ADMINFORTH_SECRET ` - your AdminForth secret - random string, for example `openssl rand -base64 32 | tr -d '\n'`
481
504
482
505
Now you can push your changes to GitHub and see how it will be deployed automatically.
0 commit comments