feat: Fleet/Collector/엣지 배포 관련 누적 작업 일괄 커밋
Build and Push Images / build-and-push (push) Has been cancelled
Build and Push Images / build-and-push (push) Has been cancelled
이전 세션들에서 작업된 아래 범위를 모두 포함: Fleet 서브시스템 (src/fleet/) - fleetDeviceService / fleetCommandService / fleetDeploymentService / fleetReleaseService - fleetMetricsService, fleetScriptService, fleetEdgeConfigService - Edge 디바이스 관리, 커맨드 발행, 배포/릴리스, 스크립트 동기화 Collector 확장 - centralMqttForwarder / centralForwarderConfigService - equipmentStateService, pythonHookRunner, scriptCache - Modbus/OPC-UA/S7/XGT 프로토콜 클라이언트 - targetDbIntrospection (저장 DB 조회) Routes / API - automationDashboardRoutes, centralForwarderRoutes, equipmentStateRoutes DB - importEdgeConfig (Python cached config → Pipeline DB) - seedDataSources (external_db_connections 초기 시드) 엣지 배포 리소스 - docker/edge/Dockerfile.backend.prod, Dockerfile.frontend.prod - docker/edge/docker-compose.edge.yml 프론트엔드 - admin/automaticMng (centralForwarder, dashboard, equipmentState) - admin/fleet (commands, devices, deployments, releases, scripts, alerts) - admin/pipeline-device 개선 (저장 DB 드롭다운, 태그 매핑 등) - ExternalDbConnectionModal, ScriptsManagerDialog 등 신규 컴포넌트 - lib/api: automationDashboard, centralForwarder, equipmentState, fleet docs/ - EDGE_SERVER_STRUCTURE, FLEET_COMPLETE, FLEET_EDGE_INTEGRATION, FLEET_HOOK_INTEGRATION Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,9 @@ FROM node:20-bookworm-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 시스템 패키지 설치 (curl: 헬스 체크용)
|
||||
# 시스템 패키지 설치 (curl: 헬스 체크용, python3: Fleet Hook dry-run 용)
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends openssl ca-certificates curl \
|
||||
&& apt-get install -y --no-install-recommends openssl ca-certificates curl python3 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# package.json 복사 및 의존성 설치 (개발 의존성 포함)
|
||||
|
||||
@@ -9,6 +9,8 @@ services:
|
||||
- ../../backend-node/.env
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "1883:1883" # MQTT TCP (내장 브로커)
|
||||
- "8083:8083" # MQTT WebSocket
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
environment:
|
||||
|
||||
@@ -10,14 +10,17 @@ services:
|
||||
environment:
|
||||
- NEXT_PUBLIC_API_URL=http://localhost:8080/api
|
||||
- SERVER_API_URL=http://pipeline-backend:8080
|
||||
- NODE_OPTIONS=--max-old-space-size=8192
|
||||
- NODE_OPTIONS=--max-old-space-size=6144
|
||||
- NEXT_TELEMETRY_DISABLED=1
|
||||
- WATCHPACK_POLLING=true
|
||||
- WATCHPACK_POLLING_INTERVAL=3000
|
||||
# volumes:
|
||||
# - ../../frontend:/app # 소스 마운트 (Docker for Mac에서 컴파일 느림 → 비활성화)
|
||||
# - /app/node_modules
|
||||
# - /app/.next
|
||||
mem_limit: 8g
|
||||
mem_reservation: 3g
|
||||
mem_swappiness: 0
|
||||
volumes:
|
||||
- ../../frontend:/app:delegated
|
||||
- /app/node_modules
|
||||
- /app/.next
|
||||
networks:
|
||||
- pipeline-network
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# ============================================================
|
||||
# Pipeline Edge 환경변수 예제 (이 파일을 .env로 복사 후 채우세요)
|
||||
# ============================================================
|
||||
|
||||
# ─── DB 연결 ─────────────────────────────────────────
|
||||
# 옵션 A: IDC 중앙 PostgreSQL 사용 (간단, 네트워크 의존)
|
||||
DATABASE_URL=postgresql://vexplor_pipeline_user:pipline0909!!@211.115.91.170:11141/vexplor_pipeline
|
||||
|
||||
# 옵션 B: 엣지 로컬 PostgreSQL 쓰려면 같은 compose에 postgres 서비스 추가 후:
|
||||
# DATABASE_URL=postgresql://pipeline:password@postgres:5432/pipeline
|
||||
|
||||
# ─── 보안 (반드시 바꿀 것) ───────────────────────────
|
||||
JWT_SECRET=change-me-to-strong-random-secret-at-least-32-chars
|
||||
PASSWORD_ENCRYPTION_KEY=change-me-32-byte-hex-key-for-aes-256
|
||||
|
||||
# ─── 엣지 식별 ───────────────────────────────────────
|
||||
# 고객사 코드
|
||||
COMPANY_CODE=spifox
|
||||
|
||||
# 엣지 UUID (스피폭스 예: aff81fbf-9b4c-43e0-9395-566bf47c3f9c)
|
||||
EDGE_ID=aff81fbf-9b4c-43e0-9395-566bf47c3f9c
|
||||
|
||||
# ─── Pipeline 이미지 (Harbor 경로) ───────────────────
|
||||
PIPELINE_IMAGE=harbor.wace.me/vexplor_fleet/pipeline-backend:latest
|
||||
PIPELINE_FRONT_IMAGE=harbor.wace.me/vexplor_fleet/pipeline-front:latest
|
||||
@@ -0,0 +1,58 @@
|
||||
# ============================================================
|
||||
# Pipeline Backend — 엣지 배포용 프로덕션 이미지
|
||||
#
|
||||
# Python 훅 실행기용 python3 포함.
|
||||
# ts-node 대신 dist/app.js 실행 (프로덕션).
|
||||
# ============================================================
|
||||
|
||||
FROM node:20-bookworm-slim AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 시스템 패키지
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends openssl ca-certificates curl python3 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 의존성 설치 (devDependencies 포함 — tsc 빌드 필요)
|
||||
COPY package*.json ./
|
||||
RUN npm ci --prefer-offline --no-audit
|
||||
|
||||
# 소스 복사 + 빌드
|
||||
COPY tsconfig.json ./
|
||||
COPY src ./src
|
||||
COPY db ./db
|
||||
RUN npx tsc --outDir dist
|
||||
|
||||
# ── Runtime 스테이지 (작은 이미지) ──────────────────
|
||||
FROM node:20-bookworm-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Python3 + 필수 런타임만
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends openssl ca-certificates curl python3 \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
# Production 의존성만
|
||||
COPY package*.json ./
|
||||
RUN npm ci --omit=dev --prefer-offline --no-audit \
|
||||
&& npm cache clean --force
|
||||
|
||||
# 빌드 결과물 복사
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/db ./db
|
||||
|
||||
# 스토리지 폴더
|
||||
RUN mkdir -p /app/storage /app/uploads \
|
||||
&& chown -R node:node /app
|
||||
|
||||
USER node
|
||||
|
||||
EXPOSE 8080 1883 8083
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
|
||||
CMD curl -fsS http://localhost:8080/health || exit 1
|
||||
|
||||
CMD ["node", "dist/app.js"]
|
||||
@@ -0,0 +1,36 @@
|
||||
# Pipeline Frontend — 엣지 배포용 프로덕션 이미지 (next build + next start)
|
||||
|
||||
FROM node:20-bookworm-slim AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --prefer-offline --no-audit
|
||||
|
||||
COPY . .
|
||||
|
||||
# 프로덕션 빌드
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
RUN npm run build
|
||||
|
||||
# ── Runtime 스테이지 ───────────────────────────────
|
||||
FROM node:20-bookworm-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3000
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --omit=dev --prefer-offline --no-audit \
|
||||
&& npm cache clean --force
|
||||
|
||||
# 빌드 결과물
|
||||
COPY --from=builder /app/.next ./.next
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/next.config.* ./
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["npx", "next", "start", "-p", "3000"]
|
||||
@@ -0,0 +1,181 @@
|
||||
# Pipeline Edge Deployment
|
||||
|
||||
스피폭스 등 고객사 엣지 서버에 Pipeline을 올려 기존 Python data-collector + Kafka + forwarder를 **완전 대체**합니다.
|
||||
|
||||
## 기존 vs 신규 구조
|
||||
|
||||
```
|
||||
[기존]
|
||||
PLC → Python data-collector → 로컬 Kafka → kafka-to-central-mqtt → IDC EMQX → TimescaleDB
|
||||
|
||||
[신규 — Pipeline 단일 서비스]
|
||||
PLC → Pipeline (XGT/Modbus/OPC UA/S7 직접 수집 + Python 훅 실행) → IDC EMQX → TimescaleDB
|
||||
```
|
||||
|
||||
Pipeline이 다음 역할을 모두 수행:
|
||||
- 장비 폴링 (XGT/Modbus/OPC UA/S7)
|
||||
- Python 훅 실행 (transform/filter/derived_tags, `python3` 서브프로세스)
|
||||
- 로컬 현재값 스냅샷 (`equipment_current_state`)
|
||||
- IDC MQTT 포워딩 (`dt/v1/data/{company_id}/{edge_id}`)
|
||||
- 재시도 큐 (`central_mqtt_forwarder_retry_queue`)
|
||||
- 모든 것을 UI에서 관리
|
||||
|
||||
## 1. 이미지 빌드 & 푸시 (최초 1회, 로컬에서)
|
||||
|
||||
```bash
|
||||
cd /Users/chpark/workspace/vexplor_Pipeline
|
||||
|
||||
# 백엔드 프로덕션 이미지
|
||||
docker build \
|
||||
-f docker/edge/Dockerfile.backend.prod \
|
||||
-t harbor.wace.me/vexplor_fleet/pipeline-backend:latest \
|
||||
./backend-node
|
||||
|
||||
docker push harbor.wace.me/vexplor_fleet/pipeline-backend:latest
|
||||
|
||||
# (선택) 프론트엔드 이미지 — 엣지에서 UI 직접 띄우려면
|
||||
docker build \
|
||||
-f docker/dev/frontend.Dockerfile \
|
||||
-t harbor.wace.me/vexplor_fleet/pipeline-front:latest \
|
||||
./frontend
|
||||
|
||||
docker push harbor.wace.me/vexplor_fleet/pipeline-front:latest
|
||||
```
|
||||
|
||||
## 2. 엣지 서버 준비 (스피폭스 `112.168.212.142`)
|
||||
|
||||
> ⚠️ **병행 운영 모드**
|
||||
> 기존 Python data-collector / fleet-agent / kafka-to-central-mqtt는 **절대 중지하지 않고** 그대로 둡니다.
|
||||
> Pipeline은 옆에서 별도로 기동해 "연결/수집/포워딩이 잘 되는지"만 검증합니다.
|
||||
> 안정성 확인 후 사용자가 판단해서 기존 컨테이너 중지 여부 결정.
|
||||
|
||||
```bash
|
||||
ssh wace@112.168.212.142
|
||||
|
||||
# Harbor 로그인
|
||||
docker login harbor.wace.me
|
||||
|
||||
# Pipeline 전용 디렉토리 (기존 data-collector와 분리)
|
||||
mkdir -p /home/wace/pipeline-edge
|
||||
cd /home/wace/pipeline-edge
|
||||
```
|
||||
|
||||
### 포트 충돌 확인 (기존 컨테이너와 겹치지 않는지)
|
||||
|
||||
```bash
|
||||
# 기존 스피폭스 엣지의 포트 사용 현황 확인
|
||||
docker ps --format 'table {{.Names}}\t{{.Ports}}' | grep -E '8080|1883|8083|9771'
|
||||
```
|
||||
|
||||
만약 겹치면 Pipeline 쪽 포트를 바꿔 기동 (compose에서 `ports:` 좌측 값만 수정).
|
||||
|
||||
## 3. compose + env 배치
|
||||
|
||||
`docker-compose.edge.yml`와 `.env.example`를 엣지에 업로드 후 `.env.example`를 `.env`로 복사하고 값 설정:
|
||||
|
||||
```bash
|
||||
# 로컬 → 엣지로 scp
|
||||
scp docker/edge/docker-compose.edge.yml wace@112.168.212.142:/home/wace/pipeline-edge/
|
||||
scp docker/edge/.env.example wace@112.168.212.142:/home/wace/pipeline-edge/.env
|
||||
|
||||
# 엣지에서 .env 편집
|
||||
ssh wace@112.168.212.142
|
||||
cd /home/wace/pipeline-edge
|
||||
vi .env # DATABASE_URL, JWT_SECRET, PASSWORD_ENCRYPTION_KEY, EDGE_ID 등 입력
|
||||
```
|
||||
|
||||
## 4. 기동
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.edge.yml up -d
|
||||
|
||||
# 프론트 UI도 같이 띄우려면:
|
||||
docker compose -f docker-compose.edge.yml --profile with-ui up -d
|
||||
|
||||
# Watchtower 자동 업데이트까지:
|
||||
docker compose -f docker-compose.edge.yml --profile watchtower up -d
|
||||
```
|
||||
|
||||
## 5. 검증
|
||||
|
||||
```bash
|
||||
# 헬스체크
|
||||
curl http://localhost:8080/health
|
||||
|
||||
# 부팅 로그 확인
|
||||
docker logs pipeline-backend --tail 100 | grep -iE 'collector|forwarder|script'
|
||||
|
||||
# 기대 출력:
|
||||
# ✅ 중앙 MQTT 포워더 + 장비 현재값 테이블 생성 완료
|
||||
# ✅ 프로토콜 CHECK 제약 확장 완료
|
||||
# 🔌 장비 수집기 자동 시작: N개 연결
|
||||
# [CentralForwarder] 연결됨: mqtt://211.115.91.170:31883
|
||||
```
|
||||
|
||||
- 이후 웹에서 `http://<엣지IP>:9771`로 UI 접근 (또는 중앙 Pipeline UI에서 같은 DB 공유 시 공통 사용).
|
||||
- **장비 통신** 페이지에서 PLC 연결 활성화 / 비활성화 가능
|
||||
- **Python 훅** `/admin/fleet/scripts`에서 편집 → 연결에 체크박스로 붙임 → 다음 폴링부터 자동 반영
|
||||
|
||||
## 6. 롤백 / 정리
|
||||
|
||||
기존 Python data-collector는 그대로 돌고 있으므로 **Pipeline만 내리면** 원상 복구됩니다.
|
||||
|
||||
```bash
|
||||
# Pipeline만 중지 (기존 data-collector는 영향 없음)
|
||||
cd /home/wace/pipeline-edge
|
||||
docker compose -f docker-compose.edge.yml down
|
||||
```
|
||||
|
||||
## 병행 운영 중 주의사항 — **중복 IDC 전송 방지**
|
||||
|
||||
기존 `kafka-to-central-mqtt` forwarder가 돌고 있는 상태에서 Pipeline 포워더까지 켜면 **같은 데이터가 IDC에 두 번 들어갑니다** (동일 `edge_id`/`company_id` + 동일 토픽).
|
||||
|
||||
### 해결책 (택 1)
|
||||
|
||||
**A. Pipeline 포워더는 켜지 말기 (추천 — 연결 검증만 먼저)**
|
||||
- `/admin/automaticMng/centralForwarder` 에서 포워더 설정 **비활성**(`is_enabled='N'`) 유지
|
||||
- Pipeline은 수집/UI 테스트만, IDC 전송은 기존 forwarder가 계속 담당
|
||||
|
||||
**B. 테스트용 edge_id 사용**
|
||||
- `.env`에 `EDGE_ID=spifox-pipeline-test` 같은 식별자
|
||||
- IDC TimescaleDB에서 이 edge_id만 별도로 보면서 수집값 검증
|
||||
- 검증 끝나면 실 edge_id로 변경 + 기존 forwarder 중지
|
||||
|
||||
**C. 기존 포워더 중지 (완전 대체 시점)**
|
||||
```bash
|
||||
docker stop kafka-to-central-mqtt
|
||||
# 이제 Pipeline 포워더 활성화
|
||||
```
|
||||
|
||||
## 주요 환경변수
|
||||
|
||||
| 변수 | 설명 | 필수 |
|
||||
|---|---|---|
|
||||
| `DATABASE_URL` | PostgreSQL 접속 URL | ✅ |
|
||||
| `JWT_SECRET` | JWT 서명 키 (32+ 글자) | ✅ |
|
||||
| `PASSWORD_ENCRYPTION_KEY` | AES-256 키 (32바이트 hex) | ✅ |
|
||||
| `ENABLE_AUTO_COLLECTOR` | 부팅 시 모든 활성 연결 자동 폴링 (엣지=true) | 엣지용 |
|
||||
| `COMPANY_CODE` | 고객사 식별 (예: spifox) | ✅ |
|
||||
| `EDGE_ID` | 엣지 UUID | ✅ |
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
### Python 훅 실행 에러
|
||||
```bash
|
||||
docker exec pipeline-backend python3 --version # 3.11+이어야 함
|
||||
```
|
||||
|
||||
### IDC MQTT 미연결
|
||||
```bash
|
||||
docker exec pipeline-backend node -e '
|
||||
const mqtt=require("mqtt");
|
||||
const c=mqtt.connect("mqtt://211.115.91.170:31883",{username:"ingestion",password:"ingestion_secret_prod"});
|
||||
c.on("connect",()=>{console.log("OK"); c.end();});
|
||||
c.on("error",e=>console.log("ERR",e.message));
|
||||
'
|
||||
```
|
||||
|
||||
### PLC 미연결
|
||||
```bash
|
||||
docker exec pipeline-backend sh -c 'timeout 3 bash -c "cat < /dev/tcp/192.168.101.50/2004" && echo OK || echo FAIL'
|
||||
```
|
||||
@@ -0,0 +1,107 @@
|
||||
# ============================================================
|
||||
# Pipeline Edge 배포 Compose
|
||||
#
|
||||
# 목적: 스피폭스 등 고객사 엣지 서버에 Pipeline을 올려
|
||||
# 기존 Python data-collector + Kafka + forwarder를 완전 대체
|
||||
#
|
||||
# 실행:
|
||||
# cd /home/wace/pipeline-edge
|
||||
# docker compose -f docker-compose.edge.yml up -d
|
||||
#
|
||||
# 전제:
|
||||
# - .env 파일에 DATABASE_URL, PASSWORD_ENCRYPTION_KEY, JWT_SECRET 설정
|
||||
# - Harbor 레지스트리 로그인 완료 (docker login harbor.wace.me)
|
||||
# - 엣지에서 PLC(예: 192.168.101.50:2004) 도달 가능
|
||||
# - 엣지에서 IDC EMQX (211.115.91.170:31883) 도달 가능
|
||||
# ============================================================
|
||||
|
||||
services:
|
||||
pipeline-backend:
|
||||
image: ${PIPELINE_IMAGE:-harbor.wace.me/vexplor_fleet/pipeline-backend:latest}
|
||||
container_name: pipeline-backend
|
||||
restart: always
|
||||
ports:
|
||||
- "8080:8080" # REST API + Admin UI
|
||||
- "1883:1883" # 내장 MQTT (로컬 용, 선택)
|
||||
- "8083:8083" # MQTT WebSocket (선택)
|
||||
environment:
|
||||
# ─── 핵심 ─────────────────────────────────────────
|
||||
- NODE_ENV=production
|
||||
- PORT=8080
|
||||
|
||||
# ─── DB 연결 (IDC 원격 또는 로컬 Postgres) ──────────
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
|
||||
# ─── 보안 ─────────────────────────────────────────
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- PASSWORD_ENCRYPTION_KEY=${PASSWORD_ENCRYPTION_KEY}
|
||||
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
|
||||
|
||||
# ─── 장비 수집기 자동 시작 ────────────────────────
|
||||
# 엣지에선 반드시 true — 부팅 시 DB의 모든 활성 연결 폴링 시작
|
||||
- ENABLE_AUTO_COLLECTOR=true
|
||||
|
||||
# ─── 회사/엣지 식별 ──────────────────────────────
|
||||
- COMPANY_CODE=${COMPANY_CODE:-spifox}
|
||||
- EDGE_ID=${EDGE_ID}
|
||||
|
||||
volumes:
|
||||
# 영속 데이터 (업로드, 로그 등)
|
||||
- pipeline-data:/app/storage
|
||||
- pipeline-uploads:/app/uploads
|
||||
networks:
|
||||
- pipeline-network
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ─── 프론트엔드 (선택) ──────────────────────────────
|
||||
# 엣지에서 직접 UI 접근하고 싶으면 켜기. 보통은 중앙 Pipeline UI 사용.
|
||||
pipeline-front:
|
||||
image: ${PIPELINE_FRONT_IMAGE:-harbor.wace.me/vexplor_fleet/pipeline-front:latest}
|
||||
container_name: pipeline-front
|
||||
restart: always
|
||||
ports:
|
||||
- "9771:3000"
|
||||
environment:
|
||||
- NEXT_PUBLIC_API_URL=http://localhost:8080/api
|
||||
- SERVER_API_URL=http://pipeline-backend:8080
|
||||
- NODE_OPTIONS=--max-old-space-size=2048
|
||||
networks:
|
||||
- pipeline-network
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
profiles: ["with-ui"] # docker compose --profile with-ui up 로 선택 기동
|
||||
|
||||
# ─── Watchtower (자동 업데이트) ──────────────────────
|
||||
# 기존 스피폭스 엣지와 동일한 패턴: Harbor 폴링 + 라벨 기반
|
||||
watchtower:
|
||||
image: nickfedor/watchtower:latest
|
||||
container_name: watchtower
|
||||
restart: always
|
||||
environment:
|
||||
- WATCHTOWER_POLL_INTERVAL=300
|
||||
- WATCHTOWER_CLEANUP=true
|
||||
- WATCHTOWER_LABEL_ENABLE=true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ~/.docker/config.json:/config.json:ro
|
||||
command: --interval 300
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=false"
|
||||
profiles: ["watchtower"]
|
||||
|
||||
networks:
|
||||
pipeline-network:
|
||||
driver: bridge
|
||||
name: pipeline-network
|
||||
|
||||
volumes:
|
||||
pipeline-data:
|
||||
name: pipeline-data
|
||||
pipeline-uploads:
|
||||
name: pipeline-uploads
|
||||
Reference in New Issue
Block a user