Skip to content

Commit

Permalink
feat: dynamic api url support (#49)
Browse files Browse the repository at this point in the history
* chore: update docker port to 80

* docs: helm + istio

* chore: version bump

* feat: dynamic api url support
  • Loading branch information
samjcombs authored Dec 19, 2024
1 parent e710922 commit 0680063
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ COPY --from=backend-builder /app/backend/package.json ./backend/
COPY --from=backend-builder /app/backend/node_modules ./backend/node_modules
COPY --from=frontend-builder /app/frontend/build ./frontend/build

EXPOSE 3007
ENV PORT=80
EXPOSE 80
CMD ["/bin/sh", "-c", "cd /app/backend && node dist/server.js"]

50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,58 @@ docker pull xolvio/instant-mock:<version>

### Kubernetes (K8s)

A basic Helm chart is provided to deploy InstantMock with Kubernetes. Currently, it ships with SQLite and is limited to a single replica.
A basic Helm chart is provided to deploy InstantMock with Kubernetes. Currently,
it ships with SQLite and is limited to a single replica.

> 🔮 **Coming Soon**: Full Helm chart with scaling support and PostgreSQL.

## 🚢 Kubernetes Deployment with Istio

### Basic Installation

InstantMock is designed to work seamlessly with Istio service mesh. To deploy:

1. Add the Helm repository
2. Create a values file with your domain configuration
3. Install using Helm

The minimal configuration requires:

- Your domain name
- Istio gateway configuration
- Backend URL (matching your domain)

### Example Values File

Create a `my-values.yaml` with your configuration:

- Set ingress.hosts[0].host to your domain
- Set env.BACKEND_URL to match your domain
- Keep service.type as ClusterIP (Istio handles external access)
- Port 80 is used internally (Istio handles SSL/TLS)

### Installation Command

Run Helm install with your values:

helm install instant-mock ./helm -f my-values.yaml

### Accessing the Application

Once deployed:

1. Configure your Istio Gateway
2. Point your domain DNS to the Istio ingress gateway
3. Access InstantMock through your configured domain

The application automatically detects the environment and configures itself for
production use.

> Note: SSL/TLS termination is handled by Istio at the gateway level

## 🙏 Acknowledgments

InstantMock builds on the work from gqmock, with many of the base MockServer utilities adapted and extended for seamless integration.
InstantMock builds on the work from gqmock, with many of the base MockServer
utilities adapted and extended for seamless integration.

> Made with ❤️ by the @xolvio team
4 changes: 2 additions & 2 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "backend",
"version": "1.0.0-beta.4.3",
"version": "1.0.0-beta.4.4",
"main": "dist/server.js",
"scripts": {
"build": "rm -rf dist/ && npx tsc && npm run copy-graphql",
Expand Down
36 changes: 31 additions & 5 deletions backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ logger.startup('Checking APOLLO_API_KEY presence', {
present: !!process.env.APOLLO_API_KEY,
});

const port = process.env.PORT || 3033;
const port = process.env.NODE_ENV === 'production' ? 80 : (process.env.PORT || 3033);

export const DI = {} as {
orm: MikroORM;
Expand Down Expand Up @@ -177,15 +177,41 @@ const initializeApp = async () => {
logger.api('Swagger API documentation served');
});

app.use(express.static(path.join(__dirname, '../../frontend/build')));
app.get('*', (_, res) => {
res.sendFile(path.join(__dirname, '../../frontend/build', 'index.html'));
app.get('*', (req, res, next) => {
if (req.path === '/') {
const indexPath = path.join(__dirname, '../../frontend/build', 'index.html');
let html = fs.readFileSync(indexPath, 'utf8');

const backendUrl = process.env.BACKEND_URL || 'localhost';
const port = process.env.NODE_ENV === 'production'
? ''
: `:${process.env.PORT || '3033'}`;

const runtimeConfig = {
BACKEND_URL: `http://${backendUrl}`,
BACKEND_PORT: port
};

html = html.replace(
'<head>',
`<head><script>window.__RUNTIME_CONFIG__=${JSON.stringify(runtimeConfig)};</script>`
);

return res.send(html);
}
next();
});

app.use(express.static(path.join(__dirname, '../../frontend/build')));

app.use(authMiddleware.error);

app.listen(port, () => {
logger.startup('Server running', {port, url: `http://localhost:${port}`});
logger.startup('Server running', {
port,
url: `http://localhost:${port}`,
env: process.env.NODE_ENV
});
});
};

Expand Down
4 changes: 3 additions & 1 deletion frontend/src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export const config = {
env: process.env.NODE_ENV as 'development' | 'production' | 'test',
backend: {
url: `${process.env.REACT_APP_BACKEND_URL || 'http://localhost'}:${process.env.REACT_APP_BACKEND_PORT || '3033'}`,
url: typeof window !== 'undefined' && window.__RUNTIME_CONFIG__
? `${window.__RUNTIME_CONFIG__.BACKEND_URL}${window.__RUNTIME_CONFIG__.BACKEND_PORT ? `:${window.__RUNTIME_CONFIG__.BACKEND_PORT}` : ''}`
: `${process.env.REACT_APP_BACKEND_URL || 'http://localhost'}:${process.env.REACT_APP_BACKEND_PORT || '3033'}`,
},
frontend: {
url: `${process.env.REACT_APP_FRONTEND_URL || 'http://localhost'}:${process.env.REACT_APP_FRONTEND_PORT || '3032'}`,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/types/window.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare interface Window {
__RUNTIME_CONFIG__: {
BACKEND_URL: string;
BACKEND_PORT: string;
};
}
21 changes: 19 additions & 2 deletions helm/values.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
replicaCount: 1
image:
repository: xolvio/instant-mock
tag: 1.0.0-beta.4.3
tag: 1.0.0-beta.4.4
pullPolicy: Always
service:
type: LoadBalancer
type: ClusterIP
port: 80
ingress:
enabled: true
className: istio
annotations:
kubernetes.io/ingress.class: istio
hosts:
- host: instant-mock.example.com
paths:
- path: /
pathType: Prefix
env:
- name: NODE_ENV
value: production
- name: BACKEND_URL
value: instant-mock.example.com
- name: PORT
value: '80'
resources: {}
persistence:
enabled: true
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "instant-mock",
"version": "1.0.0-beta.4.3",
"version": "1.0.0-beta.4.4",
"description": "![instant-mock-screen-cap-final](https://github.com/user-attachments/assets/de0f50d4-5a71-4e5a-b479-37c6cfa0481d)",
"main": "index.js",
"module": "true",
Expand Down

0 comments on commit 0680063

Please sign in to comment.