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
29 changes: 7 additions & 22 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,6 @@ jobs:
with:
dockerfile: Dockerfile

javascript-lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '23'
cache: 'npm'
cache-dependency-path: website/package.json

- name: Install dependencies
run: cd website && npm ci

- name: Run ESLint
uses: eslint/eslint-action@v3.0.0
with:
workdir: website

security-scan:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand All @@ -49,6 +27,12 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build Docker image
uses: docker/build-push-action@v5
with:
Expand All @@ -64,6 +48,7 @@ jobs:
command: cves
image: apostrophe-cms:test
sarif-file: docker-scan-results.sarif
only-severities: critical,high

- name: Upload scan results
uses: github/codeql-action/upload-sarif@v3
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ FROM node:23-alpine
# Create app directory and set permissions
WORKDIR /app

# Install dependencies needed for health checks with pinned version
RUN apk add --no-cache wget=1.25.0-r0

# Create a non-root user and group
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Copy package files for efficient caching
COPY website/package.json website/package-lock.json* ./

# Install dependencies with specific flags for production
RUN npm ci --only=production && \
RUN npm ci && \
# Clean npm cache to reduce image size
npm cache clean --force

Expand Down
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Apostrophe CMS Docker Compose Setup

This repository contains a complete Docker Compose setup for Apostrophe CMS with all required services.

## Services

- **Apostrophe CMS**: The main web application
- **MongoDB**: Database for Apostrophe
- **Redis**: Optional caching server for better performance
- **Mongo Express**: Web-based MongoDB admin interface

## Quick Start

1. Clone this repository
2. Start all services with Docker Compose:

```bash
docker-compose up -d
```

3. Access the Apostrophe CMS: http://localhost:3000
4. Access Mongo Express: http://localhost:8081

## Development

For development with hot reloading, use:

```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d
```

## Environment Variables

Environment variables are stored in the `.env` file. For production, you should change:

- `SESSION_SECRET`: Set to a secure random string
- `NODE_ENV`: Change to `production`

## Container Management

- **Start containers**: `docker-compose up -d`
- **Stop containers**: `docker-compose down`
- **View logs**: `docker-compose logs -f`
- **Rebuild containers**: `docker-compose up -d --build`

## Data Persistence

MongoDB and Redis data are stored in Docker volumes for persistence between restarts:

- `mongodb_data`
- `redis_data`

To remove all data and start fresh:

```bash
docker-compose down -v
```
24 changes: 24 additions & 0 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3.8'

services:
apostrophe:
# In development mode, use nodemon instead of normal start
command: npm run dev
environment:
- NODE_ENV=development
- REDIS_URI=redis://redis:6379
ports:
- "9229:9229" # For Node.js debugging
volumes:
- ./website:/app
- /app/node_modules

# Uncomment to enable Adminer for database management
# adminer:
# image: adminer:latest
# container_name: apostrophe-adminer
# ports:
# - "8080:8080"
# depends_on:
# - mongodb
# restart: unless-stopped
79 changes: 79 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
version: '3.8'

services:
# Apostrophe CMS web application
apostrophe:
build:
context: .
dockerfile: Dockerfile
container_name: apostrophe-cms
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- MONGODB_URI=mongodb://mongodb:27017/apostrophe
- SESSION_SECRET=change_this_to_a_secure_secret
volumes:
- ./website:/app
- /app/node_modules
depends_on:
- mongodb
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s

# MongoDB database
mongodb:
image: mongo:7.0
container_name: apostrophe-mongodb
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
command: mongod --quiet --logpath /dev/null
restart: unless-stopped
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
interval: 10s
timeout: 5s
retries: 3
start_period: 5s

# Mongo Express for database management (optional, development only)
mongo-express:
image: mongo-express:latest
container_name: apostrophe-mongo-express
ports:
- "8081:8081"
environment:
- ME_CONFIG_MONGODB_SERVER=mongodb
- ME_CONFIG_MONGODB_PORT=27017
- ME_CONFIG_BASICAUTH_USERNAME=admin
- ME_CONFIG_BASICAUTH_PASSWORD=password
depends_on:
- mongodb
restart: unless-stopped

# Redis for caching (optional, but recommended for production)
redis:
image: redis:7-alpine
container_name: apostrophe-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3

volumes:
mongodb_data:
redis_data:
50 changes: 50 additions & 0 deletions website/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const path = require('path');

require('apostrophe')({
shortName: 'apostrophe-site',
baseUrl: process.env.BASE_URL || 'http://localhost:3000',

// MongoDB connection string
mongo: {
uri: process.env.MONGODB_URI || 'mongodb://localhost:27017/apostrophe'
},

// Session configuration
modules: {
// Core modules configuration
'@apostrophecms/express': {
options: {
session: {
// If using Redis (recommended for production)
secret: process.env.SESSION_SECRET || 'changeme',
store: process.env.REDIS_URI ? {
connect: require('connect-redis'),
options: {
url: process.env.REDIS_URI || 'redis://localhost:6379'
}
} : {}
}
}
},

// Configure page types
'@apostrophecms/page': {
options: {
types: [
{
name: 'default-page',
label: 'Default'
},
{
name: 'home-page',
label: 'Home'
}
]
}
},

// Project page types
'default-page': {},
'home-page': {}
}
});
28 changes: 28 additions & 0 deletions website/modules/default-page/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = {
extend: '@apostrophecms/page-type',
options: {
label: 'Default Page'
},
fields: {
add: {
main: {
type: 'area',
label: 'Main Content',
options: {
widgets: {
'@apostrophecms/rich-text': {
toolbar: [ 'styles', 'bold', 'italic', 'link', 'unlink' ]
},
'@apostrophecms/image': {}
}
}
}
},
group: {
basics: {
label: 'Basics',
fields: ['title', 'main']
}
}
}
};
42 changes: 42 additions & 0 deletions website/modules/home-page/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module.exports = {
extend: '@apostrophecms/page-type',
options: {
label: 'Home Page'
},
fields: {
add: {
main: {
type: 'area',
label: 'Main Content',
options: {
widgets: {
'@apostrophecms/rich-text': {
toolbar: [ 'styles', 'bold', 'italic', 'link', 'unlink' ]
},
'@apostrophecms/image': {}
}
}
},
hero: {
type: 'area',
label: 'Hero Section',
options: {
widgets: {
'@apostrophecms/rich-text': {},
'@apostrophecms/image': {}
}
}
}
},
group: {
basics: {
label: 'Basics',
fields: ['title', 'main']
},
hero: {
label: 'Hero',
fields: ['hero']
}
}
}
};
13 changes: 13 additions & 0 deletions website/package-lock.json

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

3 changes: 2 additions & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"dependencies": {
"apostrophe": "^4.14.2",
"express": "^5.1.0",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"connect-redis": "^7.1.1"
},
"devDependencies": {
"eslint": "^9.24.0",
Expand Down