container-superposition 0.1.1 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +569 -8
- package/dist/scripts/init.js +436 -254
- package/dist/scripts/init.js.map +1 -1
- package/dist/tool/commands/doctor.d.ts +15 -0
- package/dist/tool/commands/doctor.d.ts.map +1 -0
- package/dist/tool/commands/doctor.js +862 -0
- package/dist/tool/commands/doctor.js.map +1 -0
- package/dist/tool/commands/explain.d.ts +13 -0
- package/dist/tool/commands/explain.d.ts.map +1 -0
- package/dist/tool/commands/explain.js +299 -0
- package/dist/tool/commands/explain.js.map +1 -0
- package/dist/tool/commands/list.d.ts +16 -0
- package/dist/tool/commands/list.d.ts.map +1 -0
- package/dist/tool/commands/list.js +121 -0
- package/dist/tool/commands/list.js.map +1 -0
- package/dist/tool/commands/plan.d.ts +67 -0
- package/dist/tool/commands/plan.d.ts.map +1 -0
- package/dist/tool/commands/plan.js +851 -0
- package/dist/tool/commands/plan.js.map +1 -0
- package/dist/tool/questionnaire/composer.d.ts +16 -2
- package/dist/tool/questionnaire/composer.d.ts.map +1 -1
- package/dist/tool/questionnaire/composer.js +411 -200
- package/dist/tool/questionnaire/composer.js.map +1 -1
- package/dist/tool/readme/markdown-parser.d.ts.map +1 -1
- package/dist/tool/readme/markdown-parser.js.map +1 -1
- package/dist/tool/readme/readme-generator.d.ts.map +1 -1
- package/dist/tool/readme/readme-generator.js +11 -6
- package/dist/tool/readme/readme-generator.js.map +1 -1
- package/dist/tool/schema/deployment-targets.d.ts +77 -0
- package/dist/tool/schema/deployment-targets.d.ts.map +1 -0
- package/dist/tool/schema/deployment-targets.js +91 -0
- package/dist/tool/schema/deployment-targets.js.map +1 -0
- package/dist/tool/schema/manifest-migrations.d.ts +51 -0
- package/dist/tool/schema/manifest-migrations.d.ts.map +1 -0
- package/dist/tool/schema/manifest-migrations.js +159 -0
- package/dist/tool/schema/manifest-migrations.js.map +1 -0
- package/dist/tool/schema/overlay-loader.d.ts +1 -1
- package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
- package/dist/tool/schema/overlay-loader.js +42 -14
- package/dist/tool/schema/overlay-loader.js.map +1 -1
- package/dist/tool/schema/types.d.ts +62 -2
- package/dist/tool/schema/types.d.ts.map +1 -1
- package/dist/tool/utils/gitignore.d.ts +15 -0
- package/dist/tool/utils/gitignore.d.ts.map +1 -0
- package/dist/tool/utils/gitignore.js +41 -0
- package/dist/tool/utils/gitignore.js.map +1 -0
- package/dist/tool/utils/merge.d.ts +134 -0
- package/dist/tool/utils/merge.d.ts.map +1 -0
- package/dist/tool/utils/merge.js +277 -0
- package/dist/tool/utils/merge.js.map +1 -0
- package/dist/tool/utils/port-utils.d.ts +29 -0
- package/dist/tool/utils/port-utils.d.ts.map +1 -0
- package/dist/tool/utils/port-utils.js +128 -0
- package/dist/tool/utils/port-utils.js.map +1 -0
- package/dist/tool/utils/services-export.d.ts +14 -0
- package/dist/tool/utils/services-export.d.ts.map +1 -0
- package/dist/tool/utils/services-export.js +478 -0
- package/dist/tool/utils/services-export.js.map +1 -0
- package/dist/tool/utils/summary.d.ts +69 -0
- package/dist/tool/utils/summary.d.ts.map +1 -0
- package/dist/tool/utils/summary.js +260 -0
- package/dist/tool/utils/summary.js.map +1 -0
- package/dist/tool/utils/version.d.ts +9 -0
- package/dist/tool/utils/version.d.ts.map +1 -0
- package/dist/tool/utils/version.js +32 -0
- package/dist/tool/utils/version.js.map +1 -0
- package/docs/architecture.md +25 -21
- package/docs/deployment-targets.md +150 -0
- package/docs/discovery-commands.md +442 -0
- package/docs/merge-strategy.md +700 -0
- package/docs/minimal-and-editor.md +265 -0
- package/docs/overlay-imports.md +209 -0
- package/docs/overlay-manifest-refactoring.md +2 -2
- package/docs/overlay-metadata-archive.md +1 -1
- package/docs/overlays.md +139 -28
- package/docs/presets-architecture.md +3 -3
- package/docs/presets.md +1 -1
- package/docs/publishing.md +36 -35
- package/docs/team-workflow.md +540 -0
- package/overlays/.presets/data-engineering.yml +392 -0
- package/overlays/.presets/event-sourced-service.yml +262 -0
- package/overlays/.presets/frontend.yml +287 -0
- package/overlays/.presets/k8s-operator-dev.yml +462 -0
- package/overlays/{presets → .presets}/microservice.yml +32 -6
- package/overlays/.presets/web-api.yml +129 -0
- package/overlays/.registry/README.md +1 -1
- package/overlays/.registry/deployment-targets.yml +54 -0
- package/overlays/.shared/README.md +43 -0
- package/overlays/.shared/compose/common-healthchecks.yml +38 -0
- package/overlays/.shared/otel/instrumentation.env +20 -0
- package/overlays/.shared/otel/otel-base-config.yaml +30 -0
- package/overlays/.shared/vscode/recommended-extensions.json +14 -0
- package/overlays/README.md +1 -1
- package/overlays/cloudflared/README.md +190 -0
- package/overlays/cloudflared/devcontainer.patch.json +3 -0
- package/overlays/cloudflared/overlay.yml +15 -0
- package/overlays/cloudflared/setup.sh +49 -0
- package/overlays/cloudflared/verify.sh +21 -0
- package/overlays/codex/overlay.yml +1 -0
- package/overlays/direnv/README.md +6 -4
- package/overlays/direnv/setup.sh +0 -12
- package/overlays/duckdb/README.md +274 -0
- package/overlays/duckdb/devcontainer.patch.json +10 -0
- package/overlays/duckdb/overlay.yml +17 -0
- package/overlays/duckdb/setup.sh +45 -0
- package/overlays/duckdb/verify.sh +32 -0
- package/overlays/git-helpers/overlay.yml +1 -0
- package/overlays/grafana/README.md +5 -5
- package/overlays/grafana/dashboard-provider.yml +1 -1
- package/overlays/grafana/docker-compose.yml +2 -2
- package/overlays/grafana/overlay.yml +6 -1
- package/overlays/grpc-tools/README.md +242 -0
- package/overlays/grpc-tools/devcontainer.patch.json +14 -0
- package/overlays/grpc-tools/overlay.yml +14 -0
- package/overlays/grpc-tools/setup.sh +57 -0
- package/overlays/grpc-tools/verify.sh +47 -0
- package/overlays/jaeger/overlay.yml +16 -3
- package/overlays/jupyter/.env.example +6 -0
- package/overlays/jupyter/README.md +210 -0
- package/overlays/jupyter/devcontainer.patch.json +14 -0
- package/overlays/jupyter/docker-compose.yml +23 -0
- package/overlays/jupyter/overlay.yml +18 -0
- package/overlays/jupyter/verify.sh +35 -0
- package/overlays/keycloak/.env.example +5 -0
- package/overlays/keycloak/README.md +238 -0
- package/overlays/keycloak/devcontainer.patch.json +17 -0
- package/overlays/keycloak/docker-compose.yml +32 -0
- package/overlays/keycloak/overlay.yml +23 -0
- package/overlays/keycloak/verify.sh +54 -0
- package/overlays/kind/README.md +221 -0
- package/overlays/kind/devcontainer.patch.json +10 -0
- package/overlays/kind/overlay.yml +18 -0
- package/overlays/kind/setup.sh +43 -0
- package/overlays/kind/verify.sh +40 -0
- package/overlays/localstack/.env.example +6 -0
- package/overlays/localstack/README.md +188 -0
- package/overlays/localstack/devcontainer.patch.json +21 -0
- package/overlays/localstack/docker-compose.yml +25 -0
- package/overlays/localstack/overlay.yml +18 -0
- package/overlays/localstack/verify.sh +47 -0
- package/overlays/loki/overlay.yml +6 -1
- package/overlays/mailpit/.env.example +4 -0
- package/overlays/mailpit/README.md +191 -0
- package/overlays/mailpit/devcontainer.patch.json +20 -0
- package/overlays/mailpit/docker-compose.yml +17 -0
- package/overlays/mailpit/overlay.yml +26 -0
- package/overlays/mailpit/verify.sh +52 -0
- package/overlays/modern-cli-tools/overlay.yml +1 -0
- package/overlays/mongodb/overlay.yml +12 -2
- package/overlays/mysql/overlay.yml +12 -2
- package/overlays/nats/overlay.yml +12 -2
- package/overlays/ngrok/overlay.yml +2 -1
- package/overlays/openapi-tools/README.md +243 -0
- package/overlays/openapi-tools/devcontainer.patch.json +10 -0
- package/overlays/openapi-tools/overlay.yml +16 -0
- package/overlays/openapi-tools/setup.sh +45 -0
- package/overlays/openapi-tools/verify.sh +51 -0
- package/overlays/otel-collector/overlay.yml.example +26 -0
- package/overlays/postgres/overlay.yml +6 -1
- package/overlays/prometheus/overlay.yml +6 -1
- package/overlays/python/README.md +51 -35
- package/overlays/python/devcontainer.patch.json +7 -4
- package/overlays/python/setup.sh +50 -23
- package/overlays/python/verify.sh +29 -1
- package/overlays/rabbitmq/overlay.yml +12 -2
- package/overlays/redis/overlay.yml +6 -1
- package/overlays/tilt/README.md +259 -0
- package/overlays/tilt/devcontainer.patch.json +17 -0
- package/overlays/tilt/overlay.yml +19 -0
- package/overlays/tilt/setup.sh +25 -0
- package/overlays/tilt/verify.sh +24 -0
- package/package.json +8 -6
- package/tool/README.md +12 -16
- package/tool/schema/overlay-manifest.schema.json +64 -4
- package/tool/schema/superposition-manifest.schema.json +104 -0
- package/overlays/presets/web-api.yml +0 -109
- /package/overlays/{presets → .presets}/docs-site.yml +0 -0
- /package/overlays/{presets → .presets}/fullstack.yml +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# LocalStack Overlay
|
|
2
|
+
|
|
3
|
+
Local AWS cloud stack for development and testing without requiring an AWS account.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **LocalStack** - Full AWS cloud emulator running locally
|
|
8
|
+
- **Multiple AWS Services** - S3, DynamoDB, SQS, SNS, Lambda, CloudFormation, and more
|
|
9
|
+
- **Docker Compose service** - Runs as separate container
|
|
10
|
+
- **Persistent storage** - Data survives container restarts
|
|
11
|
+
- **Pre-configured environment** - AWS CLI ready to use with LocalStack endpoints
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
This overlay adds LocalStack as a Docker Compose service that emulates AWS cloud services locally. The service runs in its own container and is accessible from your development container via the hostname `localstack`.
|
|
16
|
+
|
|
17
|
+
**Architecture:**
|
|
18
|
+
|
|
19
|
+
- Edge API endpoint: `http://localstack:4566` (all services)
|
|
20
|
+
- S3 endpoint: `http://localstack:4571` (S3-specific)
|
|
21
|
+
- Services run inside LocalStack container
|
|
22
|
+
- Data persisted to Docker volume
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
### Environment Variables
|
|
27
|
+
|
|
28
|
+
The overlay includes a `.env.example` file. Copy it to `.env` and customize:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd .devcontainer
|
|
32
|
+
cp .env.example .env
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Default values (.env.example):**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# LocalStack Configuration
|
|
39
|
+
LOCALSTACK_VERSION=latest
|
|
40
|
+
LOCALSTACK_SERVICES=s3,sqs,sns,dynamodb,lambda,cloudformation
|
|
41
|
+
LOCALSTACK_DEBUG=0
|
|
42
|
+
LOCALSTACK_EDGE_PORT=4566
|
|
43
|
+
LOCALSTACK_S3_PORT=4571
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Available Services
|
|
47
|
+
|
|
48
|
+
LocalStack supports many AWS services. Common ones include:
|
|
49
|
+
|
|
50
|
+
- **Storage**: S3, EFS
|
|
51
|
+
- **Databases**: DynamoDB, RDS, Redshift
|
|
52
|
+
- **Messaging**: SQS, SNS, Kinesis
|
|
53
|
+
- **Compute**: Lambda, ECS, Batch
|
|
54
|
+
- **Infrastructure**: CloudFormation, CloudWatch
|
|
55
|
+
|
|
56
|
+
Set `LOCALSTACK_SERVICES` to enable specific services or use `LOCALSTACK_SERVICES=` (empty) to enable all.
|
|
57
|
+
|
|
58
|
+
### Port Configuration
|
|
59
|
+
|
|
60
|
+
The default ports (4566, 4571) can be changed via the `--port-offset` option when initializing the devcontainer:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm run init -- --port-offset 100 --stack compose --cloud localstack
|
|
64
|
+
# LocalStack Edge will be on port 4666, S3 on port 4671
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Common Commands
|
|
68
|
+
|
|
69
|
+
### AWS CLI Usage
|
|
70
|
+
|
|
71
|
+
The `aws-cli` overlay integrates seamlessly with LocalStack:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# AWS CLI automatically uses LocalStack endpoints via AWS_ENDPOINT_URL
|
|
75
|
+
aws s3 ls
|
|
76
|
+
aws s3 mb s3://my-bucket
|
|
77
|
+
aws s3 cp myfile.txt s3://my-bucket/
|
|
78
|
+
|
|
79
|
+
# DynamoDB
|
|
80
|
+
aws dynamodb list-tables
|
|
81
|
+
aws dynamodb create-table --table-name MyTable \
|
|
82
|
+
--attribute-definitions AttributeName=id,AttributeType=S \
|
|
83
|
+
--key-schema AttributeName=id,KeyType=HASH \
|
|
84
|
+
--billing-mode PAY_PER_REQUEST
|
|
85
|
+
|
|
86
|
+
# SQS
|
|
87
|
+
aws sqs list-queues
|
|
88
|
+
aws sqs create-queue --queue-name my-queue
|
|
89
|
+
aws sqs send-message --queue-url http://localstack:4566/000000000000/my-queue \
|
|
90
|
+
--message-body "Hello LocalStack"
|
|
91
|
+
|
|
92
|
+
# Lambda
|
|
93
|
+
aws lambda list-functions
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Health Check
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Check LocalStack health
|
|
100
|
+
curl http://localstack:4566/_localstack/health
|
|
101
|
+
|
|
102
|
+
# Check specific service
|
|
103
|
+
curl http://localstack:4566/_localstack/health | jq '.services.s3'
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Direct API Calls
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# S3 via REST API
|
|
110
|
+
curl http://localstack:4566/my-bucket
|
|
111
|
+
|
|
112
|
+
# List buckets
|
|
113
|
+
aws --endpoint-url=http://localstack:4566 s3 ls
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Use Cases
|
|
117
|
+
|
|
118
|
+
- **Cloud development without AWS account** - Develop and test AWS-based applications locally
|
|
119
|
+
- **Integration testing** - Test cloud integrations without external dependencies
|
|
120
|
+
- **Learning AWS services** - Experiment with AWS APIs without cost
|
|
121
|
+
- **CI/CD pipelines** - Run AWS-dependent tests in CI without credentials
|
|
122
|
+
- **Event-driven architectures** - Test SQS, SNS, Lambda workflows locally
|
|
123
|
+
|
|
124
|
+
**Integrates well with:**
|
|
125
|
+
|
|
126
|
+
- `aws-cli` - AWS command-line interface (suggested)
|
|
127
|
+
- `terraform` - Infrastructure as Code testing
|
|
128
|
+
- `pulumi` - Infrastructure as Code testing
|
|
129
|
+
- Node.js, Python, .NET - Application development with AWS SDK
|
|
130
|
+
|
|
131
|
+
## Differences from Real AWS
|
|
132
|
+
|
|
133
|
+
LocalStack aims for high fidelity but has some differences:
|
|
134
|
+
|
|
135
|
+
- **Authentication** - Uses test credentials (no real IAM)
|
|
136
|
+
- **Performance** - May be faster or slower than real AWS
|
|
137
|
+
- **Feature parity** - Not all AWS features supported
|
|
138
|
+
- **Behavior** - Some edge cases may differ
|
|
139
|
+
|
|
140
|
+
For production deployments, always test on real AWS.
|
|
141
|
+
|
|
142
|
+
## Troubleshooting
|
|
143
|
+
|
|
144
|
+
### Service Not Ready
|
|
145
|
+
|
|
146
|
+
If LocalStack takes time to start:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Check logs
|
|
150
|
+
docker-compose logs localstack
|
|
151
|
+
|
|
152
|
+
# Wait for health check
|
|
153
|
+
curl http://localstack:4566/_localstack/health
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Connection Refused
|
|
157
|
+
|
|
158
|
+
Ensure the service is running:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Check service status
|
|
162
|
+
docker-compose ps localstack
|
|
163
|
+
|
|
164
|
+
# Restart if needed
|
|
165
|
+
docker-compose restart localstack
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Services Not Available
|
|
169
|
+
|
|
170
|
+
Enable specific services in `.env`:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
LOCALSTACK_SERVICES=s3,dynamodb,sqs,sns,lambda
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## References
|
|
177
|
+
|
|
178
|
+
- [LocalStack Documentation](https://docs.localstack.cloud/)
|
|
179
|
+
- [LocalStack GitHub](https://github.com/localstack/localstack)
|
|
180
|
+
- [Supported AWS Services](https://docs.localstack.cloud/user-guide/aws/feature-coverage/)
|
|
181
|
+
- [AWS CLI with LocalStack](https://docs.localstack.cloud/user-guide/integrations/aws-cli/)
|
|
182
|
+
|
|
183
|
+
**Related Overlays:**
|
|
184
|
+
|
|
185
|
+
- `aws-cli` - AWS command-line interface
|
|
186
|
+
- `terraform` - Infrastructure as Code
|
|
187
|
+
- `pulumi` - Infrastructure as Code
|
|
188
|
+
- `nodejs`, `python`, `dotnet` - Application development
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
|
|
3
|
+
"runServices": ["localstack"],
|
|
4
|
+
"forwardPorts": [4566, 4571],
|
|
5
|
+
"portsAttributes": {
|
|
6
|
+
"4566": {
|
|
7
|
+
"label": "LocalStack Edge",
|
|
8
|
+
"onAutoForward": "notify"
|
|
9
|
+
},
|
|
10
|
+
"4571": {
|
|
11
|
+
"label": "LocalStack S3",
|
|
12
|
+
"onAutoForward": "ignore"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"remoteEnv": {
|
|
16
|
+
"AWS_ENDPOINT_URL": "http://localstack:4566",
|
|
17
|
+
"AWS_ACCESS_KEY_ID": "test",
|
|
18
|
+
"AWS_SECRET_ACCESS_KEY": "test",
|
|
19
|
+
"AWS_DEFAULT_REGION": "us-east-1"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
localstack:
|
|
5
|
+
image: localstack/localstack:${LOCALSTACK_VERSION:-latest}
|
|
6
|
+
restart: unless-stopped
|
|
7
|
+
volumes:
|
|
8
|
+
- localstack-data:/var/lib/localstack
|
|
9
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
10
|
+
environment:
|
|
11
|
+
SERVICES: ${LOCALSTACK_SERVICES:-s3,sqs,sns,dynamodb,lambda,cloudformation}
|
|
12
|
+
DEBUG: ${LOCALSTACK_DEBUG:-0}
|
|
13
|
+
DATA_DIR: /var/lib/localstack
|
|
14
|
+
DOCKER_HOST: unix:///var/run/docker.sock
|
|
15
|
+
ports:
|
|
16
|
+
- '${LOCALSTACK_EDGE_PORT:-4566}:4566'
|
|
17
|
+
- '${LOCALSTACK_S3_PORT:-4571}:4571'
|
|
18
|
+
networks:
|
|
19
|
+
- devnet
|
|
20
|
+
|
|
21
|
+
volumes:
|
|
22
|
+
localstack-data:
|
|
23
|
+
|
|
24
|
+
networks:
|
|
25
|
+
devnet:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: localstack
|
|
2
|
+
name: LocalStack
|
|
3
|
+
description: Local AWS cloud stack for development and testing
|
|
4
|
+
category: cloud
|
|
5
|
+
supports:
|
|
6
|
+
- compose
|
|
7
|
+
requires: []
|
|
8
|
+
suggests:
|
|
9
|
+
- aws-cli
|
|
10
|
+
conflicts: []
|
|
11
|
+
tags:
|
|
12
|
+
- cloud
|
|
13
|
+
- aws
|
|
14
|
+
- testing
|
|
15
|
+
- localstack
|
|
16
|
+
ports:
|
|
17
|
+
- 4566
|
|
18
|
+
- 4571
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Verification script for LocalStack overlay
|
|
3
|
+
# Confirms LocalStack is running and accessible
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🔍 Verifying LocalStack overlay..."
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Check if LocalStack service is running
|
|
11
|
+
echo "1️⃣ Checking LocalStack service..."
|
|
12
|
+
if command -v curl &> /dev/null; then
|
|
13
|
+
# Wait up to 30 seconds for LocalStack to be ready
|
|
14
|
+
LOCALSTACK_READY=false
|
|
15
|
+
for i in {1..30}; do
|
|
16
|
+
if curl -s http://localstack:4566/_localstack/health &> /dev/null; then
|
|
17
|
+
echo " ✅ LocalStack service is ready"
|
|
18
|
+
LOCALSTACK_READY=true
|
|
19
|
+
break
|
|
20
|
+
fi
|
|
21
|
+
sleep 1
|
|
22
|
+
done
|
|
23
|
+
|
|
24
|
+
if [ "$LOCALSTACK_READY" = false ]; then
|
|
25
|
+
echo " ❌ LocalStack service not ready after 30 seconds"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
else
|
|
29
|
+
echo " ⚠️ curl not found, skipping service check"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Check LocalStack health
|
|
33
|
+
echo ""
|
|
34
|
+
echo "2️⃣ Checking LocalStack health..."
|
|
35
|
+
if command -v curl &> /dev/null; then
|
|
36
|
+
HEALTH=$(curl -s http://localstack:4566/_localstack/health)
|
|
37
|
+
if [ -n "$HEALTH" ]; then
|
|
38
|
+
echo " ✅ LocalStack health endpoint responding"
|
|
39
|
+
echo "$HEALTH" | head -3
|
|
40
|
+
else
|
|
41
|
+
echo " ❌ LocalStack health check failed"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo ""
|
|
47
|
+
echo "✅ LocalStack overlay verification complete"
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Mailpit Overlay
|
|
2
|
+
|
|
3
|
+
Email testing tool that captures all outbound emails, with a web UI for browsing and an API for automated testing.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Mailpit** - Fast, lightweight email testing tool
|
|
8
|
+
- **Web UI** - Beautiful interface for viewing captured emails (port 8025)
|
|
9
|
+
- **SMTP server** - Accepts all email without authentication (port 1025)
|
|
10
|
+
- **REST API** - Programmatic access to captured messages
|
|
11
|
+
- **Search and filter** - Find emails by recipient, subject, or content
|
|
12
|
+
- **No accidental sends** - All emails are captured locally, never delivered
|
|
13
|
+
|
|
14
|
+
## How It Works
|
|
15
|
+
|
|
16
|
+
This overlay adds Mailpit as a Docker Compose service. Configure your application to send emails via SMTP to `mailpit:1025` (from inside the container) and all emails will be captured and visible in the web UI.
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
### Environment Variables
|
|
21
|
+
|
|
22
|
+
The overlay includes a `.env.example` file. Copy it to `.env` and customize:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd .devcontainer
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Default values (.env.example):**
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Mailpit Configuration
|
|
33
|
+
MAILPIT_VERSION=latest
|
|
34
|
+
MAILPIT_UI_PORT=8025
|
|
35
|
+
MAILPIT_SMTP_PORT=1025
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### SMTP Settings for Your Application
|
|
39
|
+
|
|
40
|
+
Configure your application to use these settings:
|
|
41
|
+
|
|
42
|
+
| Setting | Value |
|
|
43
|
+
| -------------- | ------------------------------------------------------ |
|
|
44
|
+
| SMTP host | `mailpit` (inside container) / `localhost` (from host) |
|
|
45
|
+
| SMTP port | `1025` |
|
|
46
|
+
| Authentication | None required |
|
|
47
|
+
| TLS/SSL | Not required |
|
|
48
|
+
|
|
49
|
+
## Common Commands
|
|
50
|
+
|
|
51
|
+
### View Captured Emails
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Open web UI in browser
|
|
55
|
+
open http://localhost:8025
|
|
56
|
+
|
|
57
|
+
# List messages via API
|
|
58
|
+
curl -s http://localhost:8025/api/v1/messages | jq .
|
|
59
|
+
|
|
60
|
+
# Get message count
|
|
61
|
+
curl -s http://localhost:8025/api/v1/info | jq .Messages
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Search Emails
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Search by query
|
|
68
|
+
curl -s "http://localhost:8025/api/v1/messages?query=password+reset" | jq .
|
|
69
|
+
|
|
70
|
+
# Filter by recipient
|
|
71
|
+
curl -s "http://localhost:8025/api/v1/messages?query=to:user@example.com" | jq .
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Clear All Emails
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Delete all messages via API
|
|
78
|
+
curl -s -X DELETE http://localhost:8025/api/v1/messages
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Application Configuration Examples
|
|
82
|
+
|
|
83
|
+
### Node.js (using nodemailer)
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
import nodemailer from 'nodemailer';
|
|
87
|
+
|
|
88
|
+
const transporter = nodemailer.createTransport({
|
|
89
|
+
host: process.env.SMTP_HOST || 'mailpit',
|
|
90
|
+
port: parseInt(process.env.SMTP_PORT || '1025'),
|
|
91
|
+
secure: false,
|
|
92
|
+
auth: null, // No authentication needed
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
await transporter.sendMail({
|
|
96
|
+
from: 'noreply@example.com',
|
|
97
|
+
to: 'user@example.com',
|
|
98
|
+
subject: 'Welcome!',
|
|
99
|
+
text: 'Welcome to our app.',
|
|
100
|
+
html: '<b>Welcome to our app.</b>',
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Python (using smtplib)
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import smtplib
|
|
108
|
+
from email.mime.text import MIMEText
|
|
109
|
+
import os
|
|
110
|
+
|
|
111
|
+
def send_email(to, subject, body):
|
|
112
|
+
msg = MIMEText(body, 'html')
|
|
113
|
+
msg['Subject'] = subject
|
|
114
|
+
msg['From'] = 'noreply@example.com'
|
|
115
|
+
msg['To'] = to
|
|
116
|
+
|
|
117
|
+
smtp_host = os.getenv('SMTP_HOST', 'mailpit')
|
|
118
|
+
smtp_port = int(os.getenv('SMTP_PORT', '1025'))
|
|
119
|
+
|
|
120
|
+
with smtplib.SMTP(smtp_host, smtp_port) as server:
|
|
121
|
+
server.sendmail(msg['From'], [to], msg.as_string())
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### .NET (using MailKit)
|
|
125
|
+
|
|
126
|
+
```csharp
|
|
127
|
+
using MailKit.Net.Smtp;
|
|
128
|
+
using MimeKit;
|
|
129
|
+
|
|
130
|
+
var message = new MimeMessage();
|
|
131
|
+
message.From.Add(new MailboxAddress("App", "noreply@example.com"));
|
|
132
|
+
message.To.Add(new MailboxAddress("User", "user@example.com"));
|
|
133
|
+
message.Subject = "Welcome!";
|
|
134
|
+
message.Body = new TextPart("html") { Text = "<b>Welcome!</b>" };
|
|
135
|
+
|
|
136
|
+
using var client = new SmtpClient();
|
|
137
|
+
await client.ConnectAsync(
|
|
138
|
+
Environment.GetEnvironmentVariable("SMTP_HOST") ?? "mailpit",
|
|
139
|
+
int.Parse(Environment.GetEnvironmentVariable("SMTP_PORT") ?? "1025"),
|
|
140
|
+
false
|
|
141
|
+
);
|
|
142
|
+
await client.SendAsync(message);
|
|
143
|
+
await client.DisconnectAsync(true);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Automated Testing
|
|
147
|
+
|
|
148
|
+
### Check Email was Sent
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Send test email, then verify it was received
|
|
152
|
+
curl -s http://localhost:8025/api/v1/messages | jq '.messages | length'
|
|
153
|
+
# Should be > 0
|
|
154
|
+
|
|
155
|
+
# Get latest email subject
|
|
156
|
+
curl -s http://localhost:8025/api/v1/messages | jq '.messages[0].Subject'
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Integration Test Pattern
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
// After triggering an action that sends email:
|
|
163
|
+
const response = await fetch('http://localhost:8025/api/v1/messages');
|
|
164
|
+
const data = await response.json();
|
|
165
|
+
|
|
166
|
+
const latestEmail = data.messages[0];
|
|
167
|
+
expect(latestEmail.To[0].Address).toBe('user@example.com');
|
|
168
|
+
expect(latestEmail.Subject).toBe('Password Reset');
|
|
169
|
+
|
|
170
|
+
// Clean up for next test
|
|
171
|
+
await fetch('http://localhost:8025/api/v1/messages', { method: 'DELETE' });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Use Cases
|
|
175
|
+
|
|
176
|
+
- **Email flow testing** - Verify registration, password reset, and notification emails
|
|
177
|
+
- **Template development** - Preview rendered HTML email templates
|
|
178
|
+
- **Integration testing** - Assert emails are sent with correct content
|
|
179
|
+
- **No accidental sends** - Safely test in development without real email delivery
|
|
180
|
+
|
|
181
|
+
## References
|
|
182
|
+
|
|
183
|
+
- [Mailpit Documentation](https://mailpit.axllent.org/docs/)
|
|
184
|
+
- [Mailpit API Reference](https://mailpit.axllent.org/docs/api-v1/)
|
|
185
|
+
- [Mailpit GitHub](https://github.com/axllent/mailpit)
|
|
186
|
+
|
|
187
|
+
**Related Overlays:**
|
|
188
|
+
|
|
189
|
+
- `nodejs` - Node.js with nodemailer
|
|
190
|
+
- `python` - Python email development
|
|
191
|
+
- `dotnet` - .NET with MailKit
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
|
|
3
|
+
"runServices": ["mailpit"],
|
|
4
|
+
"forwardPorts": [8025, 1025],
|
|
5
|
+
"portsAttributes": {
|
|
6
|
+
"8025": {
|
|
7
|
+
"label": "Mailpit Web UI",
|
|
8
|
+
"onAutoForward": "openBrowser"
|
|
9
|
+
},
|
|
10
|
+
"1025": {
|
|
11
|
+
"label": "Mailpit SMTP",
|
|
12
|
+
"onAutoForward": "ignore"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"remoteEnv": {
|
|
16
|
+
"SMTP_HOST": "mailpit",
|
|
17
|
+
"SMTP_PORT": "1025",
|
|
18
|
+
"MAILPIT_URL": "http://mailpit:8025"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
mailpit:
|
|
5
|
+
image: axllent/mailpit:${MAILPIT_VERSION:-latest}
|
|
6
|
+
restart: unless-stopped
|
|
7
|
+
environment:
|
|
8
|
+
MP_SMTP_AUTH_ACCEPT_ANY: '1'
|
|
9
|
+
MP_SMTP_AUTH_ALLOW_INSECURE: '1'
|
|
10
|
+
ports:
|
|
11
|
+
- '${MAILPIT_UI_PORT:-8025}:8025'
|
|
12
|
+
- '${MAILPIT_SMTP_PORT:-1025}:1025'
|
|
13
|
+
networks:
|
|
14
|
+
- devnet
|
|
15
|
+
|
|
16
|
+
networks:
|
|
17
|
+
devnet:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: mailpit
|
|
2
|
+
name: Mailpit
|
|
3
|
+
description: Email testing tool with web UI and SMTP server
|
|
4
|
+
category: dev
|
|
5
|
+
supports:
|
|
6
|
+
- compose
|
|
7
|
+
requires: []
|
|
8
|
+
suggests: []
|
|
9
|
+
conflicts: []
|
|
10
|
+
tags:
|
|
11
|
+
- dev
|
|
12
|
+
- email
|
|
13
|
+
- smtp
|
|
14
|
+
- testing
|
|
15
|
+
ports:
|
|
16
|
+
- port: 8025
|
|
17
|
+
service: mailpit
|
|
18
|
+
protocol: http
|
|
19
|
+
description: Mailpit web UI
|
|
20
|
+
path: /
|
|
21
|
+
onAutoForward: openBrowser
|
|
22
|
+
- port: 1025
|
|
23
|
+
service: mailpit
|
|
24
|
+
protocol: tcp
|
|
25
|
+
description: Mailpit SMTP server
|
|
26
|
+
onAutoForward: ignore
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Verification script for Mailpit overlay
|
|
3
|
+
# Confirms Mailpit is running and accessible
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🔍 Verifying Mailpit overlay..."
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Check if curl is available
|
|
11
|
+
echo "1️⃣ Checking curl availability..."
|
|
12
|
+
if ! command -v curl &> /dev/null; then
|
|
13
|
+
echo " ❌ curl not found"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
echo " ✅ curl found"
|
|
17
|
+
|
|
18
|
+
# Check Mailpit web UI
|
|
19
|
+
echo ""
|
|
20
|
+
echo "2️⃣ Checking Mailpit service..."
|
|
21
|
+
MAILPIT_HOST="${MAILPIT_HOST:-mailpit}"
|
|
22
|
+
MAILPIT_UI_PORT="${MAILPIT_UI_PORT:-8025}"
|
|
23
|
+
MAILPIT_READY=false
|
|
24
|
+
|
|
25
|
+
for i in {1..20}; do
|
|
26
|
+
if curl -sf "http://${MAILPIT_HOST}:${MAILPIT_UI_PORT}/api/v1/info" &> /dev/null; then
|
|
27
|
+
echo " ✅ Mailpit service is ready"
|
|
28
|
+
MAILPIT_READY=true
|
|
29
|
+
break
|
|
30
|
+
fi
|
|
31
|
+
sleep 2
|
|
32
|
+
done
|
|
33
|
+
|
|
34
|
+
if [ "$MAILPIT_READY" = false ]; then
|
|
35
|
+
echo " ❌ Mailpit service not ready after 40 seconds"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Check Mailpit API
|
|
40
|
+
echo ""
|
|
41
|
+
echo "3️⃣ Checking Mailpit API..."
|
|
42
|
+
if curl -sf "http://${MAILPIT_HOST}:${MAILPIT_UI_PORT}/api/v1/messages" &> /dev/null; then
|
|
43
|
+
echo " ✅ Mailpit API is accessible"
|
|
44
|
+
else
|
|
45
|
+
echo " ❌ Mailpit API not accessible"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
echo ""
|
|
50
|
+
echo "✅ Mailpit overlay verification complete"
|
|
51
|
+
echo " Web UI: http://localhost:${MAILPIT_UI_PORT}"
|
|
52
|
+
echo " SMTP server: mailpit:1025 (from inside container)"
|
|
@@ -13,5 +13,15 @@ tags:
|
|
|
13
13
|
- mongodb
|
|
14
14
|
- document
|
|
15
15
|
ports:
|
|
16
|
-
- 27017
|
|
17
|
-
|
|
16
|
+
- port: 27017
|
|
17
|
+
service: mongodb
|
|
18
|
+
protocol: tcp
|
|
19
|
+
description: MongoDB database connection
|
|
20
|
+
onAutoForward: notify
|
|
21
|
+
connectionStringTemplate: 'mongodb://{mongo_initdb_root_username}:{mongo_initdb_root_password}@{host}:{port}/'
|
|
22
|
+
- port: 8081
|
|
23
|
+
service: mongo-express
|
|
24
|
+
protocol: http
|
|
25
|
+
description: Mongo Express web UI
|
|
26
|
+
path: /
|
|
27
|
+
onAutoForward: openBrowser
|
|
@@ -12,5 +12,15 @@ tags:
|
|
|
12
12
|
- sql
|
|
13
13
|
- mysql
|
|
14
14
|
ports:
|
|
15
|
-
- 3306
|
|
16
|
-
|
|
15
|
+
- port: 3306
|
|
16
|
+
service: mysql
|
|
17
|
+
protocol: tcp
|
|
18
|
+
description: MySQL database connection
|
|
19
|
+
onAutoForward: notify
|
|
20
|
+
connectionStringTemplate: 'mysql://{mysql_user}:{mysql_password}@{host}:{port}/{mysql_database}'
|
|
21
|
+
- port: 8080
|
|
22
|
+
service: phpmyadmin
|
|
23
|
+
protocol: http
|
|
24
|
+
description: phpMyAdmin web UI
|
|
25
|
+
path: /
|
|
26
|
+
onAutoForward: openBrowser
|