Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 55 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Dependencies
node_modules/
npm-debug.log
yarn-error.log

# Build output
dist/

# Proto samples (will be mounted as volume)
proto_samples/

# Git
.git/
.gitignore
.gitattributes

# Documentation
*.md
README*
CHANGELOG*
LICENSE*

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Environment
.env
.env.*

# Testing
coverage/
.nyc_output/

# Docker
Dockerfile
docker-compose.yml
.dockerignore

# CI/CD
.github/
.gitlab-ci.yml
.travis.yml

# Misc
*.log
tmp/
temp/
61 changes: 61 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Stage 1: Build
FROM node:20-alpine AS builder

# Install Yarn globally
RUN corepack enable && corepack prepare yarn@1.22.22 --activate

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json yarn.lock ./

# Install all dependencies (including devDependencies for build)
# Skip scripts to prevent prepare hook from running before source is copied
RUN yarn install --frozen-lockfile --ignore-scripts

# Copy source code
COPY . .

# Build the application (compile TypeScript + copy static assets)
RUN yarn build

# Stage 2: Production
FROM node:20-alpine

# Install Yarn globally
RUN corepack enable && corepack prepare yarn@1.22.22 --activate

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json yarn.lock ./

# Install only production dependencies
# Skip scripts since we're only copying pre-built artifacts
RUN yarn install --frozen-lockfile --production --ignore-scripts

# Copy built application from builder stage
COPY --from=builder /app/dist ./dist

# Copy config directory structure (for config.json mount point)
# Note: example.config.json is already in dist/config/ from the build process
# This ensures the directory structure exists for the volume mount
COPY --from=builder /app/dist/config/example.config.json ./dist/config/

# Create proto_samples directory
RUN mkdir -p proto_samples

# Expose the default port
EXPOSE 8081

# Set NODE_ENV to production
ENV NODE_ENV=production

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:8081/', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

# Start the application
CMD ["node", "dist/index.js"]
20 changes: 20 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
services:
protodecoder-ui:
build:
context: .
dockerfile: Dockerfile
container_name: protodecoder-ui
ports:
- "8081:8081"
volumes:
- ./src/config/config.json:/app/dist/config/config.json:ro
- ./proto_samples:/app/proto_samples
restart: unless-stopped
environment:
- NODE_ENV=production
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:8081/', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
interval: 30s
timeout: 10s
start_period: 5s
retries: 3
1 change: 1 addition & 0 deletions src/config/example.config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"default_port": 8081,
"web_password": null,
"trafficlight_identifier": "AwesomeProtoSender",
"redirect_to_golbat_url": null,
"redirect_to_golbat_token": null,
Expand Down
Loading