Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
51e6c79
wip: starting migrations on docker build
tuliomir Aug 12, 2025
d361a5e
fix: migrations config pathing on script
tuliomir Aug 12, 2025
2736455
feat: dedicated container image for migration
tuliomir Aug 14, 2025
3140ecb
wip: almost working version
tuliomir Aug 15, 2025
67d373f
refactor: changed migration entrypoint
tuliomir Aug 15, 2025
0e1b8c4
wip: deamon container not working properly
tuliomir Aug 16, 2025
a75fefb
wip: working Daemon PoC, now needs refinement
tuliomir Aug 18, 2025
d37155b
fix: improved variable name for fullnode ids
tuliomir Aug 18, 2025
b2d8755
feat: aws mock
tuliomir Aug 19, 2025
d816193
fix: nodejs 22
tuliomir Aug 19, 2025
c1b64bf
feat: working serverless, worsened daemon build
tuliomir Aug 22, 2025
038f844
fix: lambda mock logger
tuliomir Aug 26, 2025
a42f5b1
refactor: Daemon Dockerfile to package folder
tuliomir Aug 26, 2025
e1fd96c
docs: adds docs to container-related files
tuliomir Aug 27, 2025
e7ec00b
docs: improves comments and removes debug cmds
tuliomir Aug 27, 2025
8ab7033
feat: build-daemon script no longer needs aws
tuliomir Aug 28, 2025
61a0188
feat: migrator image built via makefile
tuliomir Sep 1, 2025
fe8b2b2
feat: service image built via makefile
tuliomir Sep 2, 2025
f96079b
docs: Notes about image size on the Dockerfiles
tuliomir Sep 2, 2025
453f2fc
docs: images instead of builds on examples
tuliomir Sep 2, 2025
2d8b303
feat: script to run serverless with nodejs debug
tuliomir Sep 2, 2025
09c5e84
fix: removes unused code and fixes logger calls
tuliomir Sep 2, 2025
e3afa92
revert: unneeded push notification changes
tuliomir Sep 2, 2025
f6e123a
docs: improves fetch-fullnode-ids explanations
tuliomir Sep 2, 2025
712a213
docs: improves complementary envs explanations
tuliomir Sep 2, 2025
8be3a2b
docs: improves dockerized explanations
tuliomir Sep 2, 2025
bf3e5f6
test: adds coverage on aws-offline-mock
tuliomir Sep 3, 2025
739542a
refactor: simplifies conditionals
tuliomir Sep 3, 2025
bd53f73
fix: type validation on tests
tuliomir Sep 3, 2025
3a46102
fix: aws mock credentials for all tests
tuliomir Sep 3, 2025
6592873
fix: dynamic set of mock_aws
tuliomir Sep 3, 2025
c8f5556
chore: removes obsolete comments
tuliomir Sep 5, 2025
39768b8
docs: explanations on MOCK_AWS env var
tuliomir Sep 5, 2025
0d198b5
refactor: configurable complementary envs
tuliomir Sep 6, 2025
b581b4a
refactor: uses config instead of env directly
tuliomir Sep 6, 2025
089014b
docs: removes redis as a service dependency
tuliomir Sep 6, 2025
5a5b2bd
refactor: conditionally uses merge script
tuliomir Sep 8, 2025
2d2982a
fix: config validation schema
tuliomir Sep 9, 2025
2bbd9f2
refactor: mock fixtures to the tests folder
tuliomir Sep 9, 2025
6490c5f
docs: fix typo
tuliomir Sep 9, 2025
37a1016
fix: aws utils imports naming
tuliomir Sep 9, 2025
aa581a7
fix: redis password conditional
tuliomir Sep 12, 2025
df34761
Merge branch 'master' into chore/container-builds
tuliomir Sep 16, 2025
3451eac
refactor: improves docker image naming
tuliomir Sep 19, 2025
f6546e2
refactor: renames .env to .sh file
tuliomir Sep 22, 2025
5c80f9d
Merge branch 'master' into chore/container-builds
tuliomir Sep 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions Dockerfile

This file was deleted.

8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ build-and-push-daemon:
build-daemon:
bash scripts/build-daemon.sh

.PHONY: build-migrator
build-migrator:
bash scripts/build-migrator.sh

.PHONY: build-service
build-service:
bash scripts/build-service.sh

.PHONY: push-daemon
push-daemon:
bash scripts/push-daemon.sh
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,25 @@ mysql -u <user> -p <database> < cleanup.sql
```

After cleaning the database, you can reseed the HTR token as described in the previous section.

## Running Inside Containers
When running these applications inside containers, it's worth noting that there are a few Dockerfiles in this monorepo.

### 1) The Daemon container
This Dockerfile is located at `./packages/daemon` and is used to build the sync daemon image. It, however,needs a properly migrated database and all the fullnode identifiers to run correctly.

The fullnode identifiers may be fetched dynamically at startup with the use of the `FETCH_FULLNODE_IDS` environment variable, provided the remaining fullnode connection config is available. Please note that this dynamic fetching is only recommended in development environments, as the identifiers are an additional security measure on production builds.

Its image can be build using the `make build-daemon` while on the root folder.

### 2) The Migrator container
The Migrator Dockerfile is located at `./db` and is used to build the migrator image then shut off. This image is responsible for applying database migrations to the database connection passed through the environment variables.

It's specially important if the database has just been created by the dockerized environment, in which case run this migrator container before starting the daemon. This, again, is only expected in discardable development environments, as production and other more persistent databases should be managed externally.

Its image can be build using the `make build-migrator` while on the root folder.

### 3) The Wallet Service container
This is the actual serverless application containing the externally consumed API. Its Dockerfile is located at `./packages/wallet-service` and is used to build the wallet service image. It needs a healthy Daemon to run correctly.

Its image can be build using the `make build-service` while on the root folder.
66 changes: 66 additions & 0 deletions db/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright 2025 Hathor Labs
# This software is provided ‘as-is’, without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# This software cannot be redistributed unless explicitly agreed in writing with the authors.

# =========================================================================
# This Dockerfile is intended for migrating the database of a dockerized private blockchain
# for the Wallet Service Daemon.
#
# It serves only as a means to run the migration scripts in an isolated environment. The container will run only
# for as long as the migration is running, and then it will exit.
#
# The migration scripts do not cause any impact if it is ran multiple times, so it is safe to run this container
# for each deployment of the Wallet Service Daemon.
#
# The expected image size is about 250MB as of v1.9.0
#
# Sample usage in a docker-compose.yml:
# ws-migrator:
# image: hathornetwork/hathor-wallet-service-migrator
# restart: "no" # Critical: don't restart migration service
# depends_on:
# mysql: # Replace with your actual mysql service name
# condition: service_healthy
# environment:
# DB_ENDPOINT: "mysql"
# DB_NAME: "wallet_service"
# DB_USER: "wallet_service_user"
# DB_PASS: "password"
# DB_PORT: 3306
# networks:
# - hathor-privnet

# This Dockerfile is used to build and run the database migration container.
FROM node:22-alpine

WORKDIR /app

# Copy only the necessary files for the migration
COPY ./db ./db
COPY ./db/migrations ./migrations

# This will install only the exact versions of sequelize, sequelize-cli and mysql2
# that are already in use in the project, avoiding any unwanted upgrades.
# It will also install the dotenv package, but it's not as critical and we can use the latest version.
#
# Note that this migrator container does not need to have all the dependencies of the main project,
# as it will only be used to run the migration scripts. For this, a new package.json is created
# with only the necessary dependencies, reducing image size.

ARG SEQUELIZE_VERSION
ARG SEQUELIZE_CLI_VERSION
ARG MYSQL2_VERSION
RUN test -n "$SEQUELIZE_VERSION" \
&& test -n "$SEQUELIZE_CLI_VERSION" \
|| (echo "Both SEQUELIZE_VERSION and SEQUELIZE_CLI_VERSION must be set" && exit 1)
# Avoids potential conflicts with pre-installed v1.x versions of yarn
RUN npm uninstall -g yarn
RUN corepack enable
RUN echo '{"name": "migrator", "private": true}' > package.json
RUN yarn add sequelize@"$SEQUELIZE_VERSION" sequelize-cli@"$SEQUELIZE_CLI_VERSION" mysql2@"$MYSQL2_VERSION" dotenv

# Run the migration scripts
RUN cp /app/db/migration-entrypoint.sh /app;
ENTRYPOINT ["/bin/sh", "/app/migration-entrypoint.sh"]
2 changes: 1 addition & 1 deletion db/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
host: '127.0.0.1',
host: process.env.DB_ENDPOINT || '127.0.0.1',
port: process.env.DB_PORT || 3306,
dialect: 'mysql',
dialectOptions: {
Expand Down
10 changes: 10 additions & 0 deletions db/migration-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh
set -e

# Run the migration script.
# Note that this is supposed to run from the root of the repository, inside a container
corepack enable
yarn sequelize db:migrate --config db/config.js

# Run the command passed to the entrypoint (if any).
exec "$@"
File renamed without changes.
83 changes: 83 additions & 0 deletions packages/daemon/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright 2024 Hathor Labs
# This software is provided ‘as-is’, without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# This software cannot be redistributed unless explicitly agreed in writing with the authors.

# =========================================================================
# This Dockerfile is used to build and run the Wallet Service Daemon container.
# It requires:
# - A MySQL instance, properly migrated ( see /db/Dockerfile )
# - A Fullnode instance
# - A Redis instance
Comment thread
tuliomir marked this conversation as resolved.
#
# The expected image size is about 500MB as of v1.9.0
#
# See the HathorNetwork / Wallet Lib repository for a live example on how to use this Dockerfile, but in short:
# ws-daemon:
# image: hathornetwork/hathor-wallet-service-sync-daemon
# depends_on:
# ws-migrator:
# condition: service_completed_successfully
# fullnode:
# condition: service_healthy
# mysql:
# condition: service_healthy
# environment:
# ...
# ports:
# - "8081:8081"
# - "8082:8082"
# networks:
# - hathor-privnet

# Build phase
FROM node:22-alpine AS builder

WORKDIR /app

RUN apk update && apk add python3 g++ make py3-setuptools

COPY . .

# corepack will use the version of yarn specified in package.json
RUN corepack enable

# This will install dependencies for all packages, except for the lambdas since
# they are ignored in .dockerignore
RUN yarn install

RUN yarn workspace sync-daemon run build

# This will remove all dev dependencies and install production deps only
RUN yarn workspaces focus -A --production

# Run phase
FROM node:22-alpine AS dev

WORKDIR /app

# Copy only the necessary files from the build phase
COPY --from=builder /app .

WORKDIR /app/packages/daemon/

# The script should already be available from the builder stage copy
RUN cp /app/scripts/fetch-fullnode-ids.js ./fetch-fullnode-ids.js
RUN cp /app/scripts/merge-complementary-envs.sh ./merge-complementary-envs.sh
RUN chmod +x ./merge-complementary-envs.sh
Comment thread
tuliomir marked this conversation as resolved.

# The daemon could need complementary environment variables dynamically.
# The entrypoint script manages this before actually running the daemon.
ENTRYPOINT ["./merge-complementary-envs.sh"]

FROM node:22-alpine AS prod

WORKDIR /app

# Copy only the necessary files from the build phase
COPY --from=builder /app .

WORKDIR /app/packages/daemon/

CMD ["node", "dist/index.js"]
11 changes: 11 additions & 0 deletions packages/wallet-service/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
dist/
__tests__/
.git/
../../.github/
.direnv/
flake.*
node_modules/
packages/daemon
packages/wallet-service/dist/
packages/wallet-service/node_modules/
packages/common/node_modules/
1 change: 1 addition & 0 deletions packages/wallet-service/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
72 changes: 72 additions & 0 deletions packages/wallet-service/Dockerfile.dev
Comment thread
tuliomir marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright 2025 Hathor Labs
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# This software cannot be redistributed unless explicitly agreed in writing with the authors.

# =========================================================================
# This Dockerfile is used to build and run the Wallet Service container.
# It requires:
# - A MySQL instance, properly migrated ( see /db/Dockerfile )
# - A Fullnode instance
# - A started Wallet Service Daemon instance ( see /packages/daemon/Dockerfile )
#
# The expected image size is about 1800MB as of v1.9.0. This is because `serverless` is a development
# dependency and needs to be installed in the final image, reducing the optimization options for
# reducing this size.
#
# To properly connect to a dockerized private network, in the environment variables, you should set `MOCK_AWS=true`
# to avoid trying to connect to external AWS services, except if the container is being run connected to a publicly
# available network.
#
# See the HathorNetwork / Wallet Lib repository for a live example on how to use this Dockerfile, but in short:
# ws-serverless:
# image: hathornetwork/hathor-wallet-service-service
# depends_on:
# fullnode:
# condition: service_healthy
# mysql:
# condition: service_healthy
# ws-daemon:
# condition: service_started
# environment:
# IS_OFFLINE: true
# ENV MOCK_AWS=true # Necessary to avoid trying to connect to external AWS services
# ...
# ports:
# - "3000:3000"
# - "3001:3001"
# networks:
# - hathor-privnet

# Build stage
FROM node:22-alpine

# Install system dependencies needed for native modules
RUN apk add --no-cache \
python3 \
g++ \
make \
py3-setuptools \
git

WORKDIR /app

# Copy root package files
COPY . .

# Enable corepack for yarn
RUN corepack enable
RUN yarn install

WORKDIR /app/packages/wallet-service

# Expose serverless-offline default port
EXPOSE 3000
# Expose websocket port
EXPOSE 3001

RUN chmod +x ./entrypoint.sh

# Run serverless offline
ENTRYPOINT ["./entrypoint.sh"]
2 changes: 1 addition & 1 deletion packages/wallet-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ database to get the information.
The plugin `serverless-offline` is used to emulate AWS Lambda and API Gateway on a local machine.

### Requirements
1. NodeJS v16
1. NodeJS v22

### Local database
To setup a local database, you will need:
Expand Down
10 changes: 10 additions & 0 deletions packages/wallet-service/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

set -e

# When MOCK_AWS is set to true, copy the mocked AWS credentials fixtures to .aws in the working directory
if [ "$MOCK_AWS" = "true" ]; then
cp -r tests/fixtures/aws ./.aws
fi

yarn serverless offline start --host 0.0.0.0 --httpPort 3000
8 changes: 6 additions & 2 deletions packages/wallet-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
"lint": "eslint src/ tests/ --ext .js,.jsx,.ts,.tsx src tests",
"lint-fix": "eslint src/ tests/ --fix --ext .js,.jsx,.ts,.tsx src tests",
"check-types": "tsc --noemit --skipLibCheck",
"test": "jest"
"test": "jest",
"debug:offline": "node --inspect-brk ./node_modules/.bin/serverless offline start --host 0.0.0.0 --httpPort 3000"
},
"engines": {
"node": "22"
},
"author": "Hathor Labs",
"license": "MIT",
Expand Down Expand Up @@ -64,7 +68,7 @@
"serverless-api-gateway-throttling": "2.0.3",
"serverless-better-credentials": "2.0.0",
"serverless-iam-roles-per-function": "3.2.0",
"serverless-offline": "13.1.2",
"serverless-offline": "14.4.0",
Comment on lines -67 to +71
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old dependency wasn't compatible with NodeJS 22 and had to be upgraded.

"serverless-plugin-aws-alerts": "1.7.5",
"serverless-plugin-monorepo": "0.11.0",
"serverless-plugin-warmup": "8.2.1",
Expand Down
Loading