Update readme, add labs (#82)

Update readme, add labs (#82)
This commit is contained in:
Alexander Tebiev 2026-06-21 18:49:22 +02:00 committed by GitHub
parent 2b4f233d59
commit 3bae6eeb59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 215 additions and 12 deletions

62
lab/Makefile Normal file
View file

@ -0,0 +1,62 @@
-include .docker-compose.env
#export COMPOSE_FILE=docker-compose-dev.yml
# export COMPOSE_PROJECT_NAME=dev
export DOCKER_BUILDKIT?=1
export COMPOSE_CONVERT_WINDOWS_PATHS?=1
export TZ?=UTC
export BUILD_DATE?=$(shell TZ=":UTC" date '+%Y-%m-%d %H:%M:%S (%Z)')
.EXPORT_ALL_VARIABLES:
.PHONY: *
.DEFAULT_GOAL := help
THIS_FILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
DOCKER_COMPOSE_COMMAND := $(shell \
if docker compose version >/dev/null 2>&1; then echo "docker compose"; \
elif docker-compose version >/dev/null 2>&1; then echo "docker-compose"; \
else echo ""; fi)
ifeq ($(DOCKER_COMPOSE_COMMAND),)
$(error "docker compose is required")
endif
help: ## Show this help
@echo "Make Application Docker Images and Containers using Docker-Compose files in 'docker' Dir."
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m (default: help)\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-12s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
up: ## Docker compose up
$(DOCKER_COMPOSE_COMMAND) up --build --no-deps --detach --remove-orphans
start: ## Alias for up
$(MAKE) up
down: ## Docker compose down
$(DOCKER_COMPOSE_COMMAND) down --remove-orphans
stop: ## Docker compose stop
$(DOCKER_COMPOSE_COMMAND) stop
restart: ## Restart containers
$(MAKE) down
$(MAKE) up
$(info Restart completed)
update: ## Update containers
$(DOCKER_COMPOSE_COMMAND) pull
$(MAKE) up
destroy: ## Destroy containers/volumes (keep sources app folders)
$(MAKE) stop
$(DOCKER_COMPOSE_COMMAND) down --rmi all --remove-orphans
rebuild: ## Rebuild docker container (destroy & upgrade)
$(MAKE) destroy
$(MAKE) up
state: ## Show current state
$(DOCKER_COMPOSE_COMMAND) ps
logs: ## Show docker logs
$(DOCKER_COMPOSE_COMMAND) logs -f --tail=100 $(ARGS)

51
lab/README.md Normal file
View file

@ -0,0 +1,51 @@
# Local RouterOS test lab
This lab runs MikroTik RouterOS CHR for development and manual tests.
## Start the lab
```sh
make start
make state
```
RouterOS can take up to two minutes to accept SSH connections on its first boot.
The `routeros-init` container retries during that period and exits after it applies the mail settings.
## Access
| Service | Address |
| --- | --- |
| Mailpit web interface | <http://localhost:8025> |
| RouterOS WebFig | <http://localhost:12280> |
| RouterOS WinBox | `localhost:18291` |
| RouterOS SSH | `localhost:12222` |
| RouterOS Telnet | `localhost:12223` |
| RouterOS API | `localhost:18728` |
| RouterOS API over TLS | `localhost:18729` |
!! Use the RouterOS user `admin` with an empty password. Use this account inside the isolated lab.
## Mailpit and ping
Expect `ping mailpit` from RouterOS to time out. Docker DNS still resolves the `mailpit` name, and SMTP traffic can reach port `1025`.
The Docker and QEMU network path does not provide a useful ICMP health check for this service.
Test SMTP from a RouterOS terminal:
```routeros
/tool e-mail send to="lab@example.test" subject="lab test" body="mail works"
```
Open <http://localhost:8025> and check that Mailpit received the message. Use message delivery as the health check for this lab.
## Usage
```routeros
/system script run BackupAndUpdate
```
Follow the script log while it runs:
```routeros
/log print follow where message~"Bkp&Upd"
```

60
lab/compose.yaml Normal file
View file

@ -0,0 +1,60 @@
services:
mailpit:
container_name: '${COMPOSE_PROJECT_NAME}-mailpit'
image: axllent/mailpit:latest
tty: true
restart: unless-stopped
environment:
- 'TZ=${TZ:-UTC}'
- 'MP_SMTP_AUTH_ACCEPT_ANY=1'
- 'MP_SMTP_AUTH_ALLOW_INSECURE=1'
- 'MP_ALLOW_UNTRUSTED_TLS=1'
ports:
- '8025:8025' # Web UI
networks:
- default
routeros:
# https://github.com/EvilFreelancer/docker-routeros
# https://hub.docker.com/r/evilfreelancer/docker-routeros/
container_name: '${COMPOSE_PROJECT_NAME}-routeros'
image: evilfreelancer/docker-routeros:7.21.4
restart: unless-stopped
tty: true
depends_on:
mailpit:
condition: service_healthy
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
- /dev/kvm
ports:
- "12280:80"
- "12222:22"
- "12223:23"
- "18728:8728"
- "18729:8729"
- "18291:8291"
# The image keeps eth0 for QEMU host forwarding and bridges eth1 into CHR.
networks:
default:
interface_name: eth0
routeros-lan:
interface_name: eth1
routeros-init:
build:
context: ./docker/routeros-init
restart: "no"
depends_on:
routeros:
condition: service_started
networks:
- default
networks:
routeros-lan:
driver: bridge

View file

@ -0,0 +1,9 @@
FROM alpine:3.23
RUN apk add --no-cache openssh-client
COPY routeros-init.sh /usr/local/bin/routeros-init
RUN chmod +x /usr/local/bin/routeros-init
ENTRYPOINT ["/usr/local/bin/routeros-init"]

View file

@ -0,0 +1,23 @@
#!/bin/sh
set -eu
deadline="$(($(date +%s) + 120))"
while [ "$(date +%s)" -lt "$deadline" ]; do
if ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=5 \
-o PreferredAuthentications=none \
-o LogLevel=ERROR \
admin@routeros \
"/tool e-mail set server=mailpit port=1025 from=routeros@example.test tls=no"; then
echo "RouterOS e-mail settings applied."
exit 0
fi
sleep 2
done
echo "Timed out waiting for RouterOS SSH." >&2
exit 1