Docker 설치
2026.05 부터 PlantPulse Edge 의 양산/현장 표준 배포는 단일 Docker 컨테이너 이미지입니다.
7개 컴포넌트(Tomcat / Cassandra / Redis / HiveMQ / TSE / Dashboard / Node-RED)가 하나의 이미지 안에
들어있고, install.sh 가 OS 의존성부터 systemd 등록까지 처리한 뒤 plantpulse-edge.service 가
컨테이너를 관리합니다.
현장에서 1대를 빠르게 올리는 절차 요약은 빠른 설치 (install.sh)에 있습니다.
이 페이지는 그 설치가 내부에서 무엇을 하는지 — 이미지 좌표, docker run 플래그, bind mount,
EnvironmentFile, OTA — 를 깊게 파고드는 레퍼런스입니다. 일상 운영은
컨테이너 모드 운영를 봅니다.
1. 이미지 좌표
| 항목 | 값 |
|---|---|
| Registry | docker.kopens.io/pe (anonymous pull) |
| 이미지명 | plantpulse-edge |
| 전체 좌표 | docker.kopens.io/pe/plantpulse-edge:<tag> |
| Tag 형식 | YYYY.MM-YYYYMMDD-HHMM 예: 2026.11-20261103-1006 (설치 때는 latest 도 가능, OTA 는 불변 태그만) |
| 다운로드 서버 | https://product.kopens.io/plantpulse-edge/ (LAN alias) |
이미지 안 고정 경로: KOPENS_HOME=/opt/kopens, PE_HOME=/opt/kopens/plantpulse-edge,
PE_DATA_DIR=/data1, JAVA_HOME=/usr/lib/jvm/java-21-openjdk.
2. 설치 흐름 — bootstrap.sh → install.sh
2.1 원라이너
curl -fsSL https://product.kopens.io/plantpulse-edge/install.sh | sudo bash
install.sh 는 bootstrap.sh 와 동일합니다. 이 스크립트가:
- repo tarball(
plantpulse-edge-docker.tar.gz)을/opt/kopens/plantpulse-edge-docker/로 펼침 (실패 시git clonefallback) PROFILEpreset 적용(있으면, 아래 3장)install.sh본체 9단계 실행
터미널에서 직접 실행하면 묻습니다(기본 동작). 대괄호 안이 기본값이고 Enter 로 수락합니다.
EDGE(기본) — 플랫폼 주소와 API 키를 반드시 묻고, 비우면 다시 묻습니다.STANDALONE— 그 둘을 아예 묻지 않습니다.Edge id기본값은 박스마다 다릅니다(NET1 MAC 에서 유도한EDGE_3F8A21꼴). 현장 번호를 쓰시려면 여기서 입력하십시오.
curl | bash 로는 묻지 못합니다 — 값을 환경변수로 주십시오파이프로 실행하면 터미널이 붙어 있지 않아 물어볼 수 없습니다. 그때는 「물어볼 수 없다」고 말한 뒤 환경변수와 기본값으로 진행합니다(조용히 넘어가지 않습니다).
curl -fsSL https://product.kopens.io/plantpulse-edge/install.sh | \
sudo EDGE_ID=EDGE_00303 DEV_MODE=EDGE \
SERVER_HOST=<플랫폼IP> SERVER_API_KEY=<토큰> bash
값을 묻게 하려면 스크립트를 내려받아 직접 실행하십시오. 자동화(CI·무인 설치)에서는
INTERACTIVE=0 으로 확실히 꺼 두는 편이 안전합니다.
env.sh 하나입니다스크립트와 같은 폴더의 env.sh 에 적어 두면 설치가 자동으로 읽습니다. 재설치할 때도 같은 값이
그대로 쓰입니다.
2.1a 설치 중에 플랫폼 키를 «검증합니다»
DEV_MODE=EDGE 면 설정을 쓰기 전에 플랫폼에 실제로 물어봅니다. 예전에는 값이 비었는지만 보고
설치를 끝냈고, 부팅 뒤에야 모든 연결이 401 로 죽었습니다.
| 상황 | 설치기 동작 |
|---|---|
| 플랫폼에 닿지 않음 | 경고만 — 아직 안 떴거나 방화벽이 아직일 수 있습니다 |
| 서버가 5xx | 경고만 — 판정을 못 낸 것이지 키 문제가 아닙니다 |
| 401 · 403 | 🔴 중단 — 키가 거부됐습니다. 오타는 여기서 잡힙니다 |
| 400 | 🔴 중단 — 설치기 쪽 문제이니 알려 주십시오 |
플랫폼보다 먼저 설치해야 하면 SKIP_PLATFORM_VERIFY=1 로 끕니다.
2.1b 사용법은 --help 가 정본입니다
sudo bash install.sh --help # root 없이도 읽힙니다
배너와 함께 USAGE · MODE decides what else is required · IDENTITY · PLATFORM · IMAGE ·
NETWORK · SKIP FLAGS · PROFILE · AFTER INSTALL 절이 나옵니다. 이 문서에 전문을 옮겨
적지 않는 이유가 있습니다 — 옮겨 적은 사본은 조용히 낡습니다. 실제로 이 저장소에서 헤더와
코드의 기본값이 갈려 있던 일이 있었습니다.
2.2 install.sh 9단계
| # | 단계 |
|---|---|
| 1 | OS 감지 (Rocky/Alma/RHEL/Ubuntu/Debian) |
| 2 | Docker 설치 (dnf 또는 apt) |
| 3 | /data1, /etc/kopens, /var/log/kopens 디렉터리 생성 |
| 4 | sysctl + firewalld 포트 + chrony + hostname + nmcli static IP |
| 5 | /etc/kopens/app.properties 생성 (EDGE_ID / SITE_ID / 박스별 random 자격증명) |
| 6 | systemd unit 설치 — plantpulse-edge.service + OTA kopens-upgrade.path/.service |
| 7 | docker pull (cosign 서명 검증 — 설치 때는 경고만, 업그레이드 때는 검증 못 하면 중단) |
| 8 | systemctl enable --now plantpulse-edge.service |
| 9 | cron weekly cleanup 등록 |
첫 설치 시 admin / MQTT / OPC-UA / API key / keystore 비번이 박스별 random 으로 생성되어
/etc/kopens/credentials.txt (chmod 0600 root) 에 1회 저장됩니다.
3. PROFILE preset
PROFILE env 로 사이트 유형별 기본값을 한 번에 적용합니다.
| PROFILE | 적용 기본값 |
|---|---|
production | DEV_MODE=EDGE (플랫폼 SERVER_HOST/SERVER_API_KEY 명시 필요) |
staging | DEV_MODE=EDGE, EDGE_ID=EDGE_00303, SITE_ID=SITE_00001, SERVER_HOST=192.168.0.235, SKIP_COSIGN_VERIFY=1 |
standalone | DEV_MODE=STANDALONE, SKIP_COSIGN_VERIFY=1 (플랫폼 미연결) |
airgap | IMAGE_URL=tarball, SKIP_PULL=1, DEV_MODE=STANDALONE (폐쇄망 설치) |
# 양산 (플랫폼 연결)
curl -fsSL https://product.kopens.io/plantpulse-edge/install.sh \
| sudo PROFILE=production EDGE_ID=EDGE_00303 \
SERVER_HOST=10.0.0.5 SERVER_API_KEY=<uuid> bash
# 단독 운영 (플랫폼 없이)
curl -fsSL https://product.kopens.io/plantpulse-edge/install.sh \
| sudo PROFILE=standalone EDGE_ID=EDGE_LOCAL_01 bash
staging 박스는 dev 와 같은 EDGE_00303 / SITE_00001 클론입니다. 달라야 하는 건
플랫폼 연결정보(SERVER_HOST=192.168.0.235 / API key) 뿐. 플랫폼에 미등록된 site 를 쓰면
엣지 자기-진단 OPC 가 FK 위반으로 실패하므로 등록된 EDGE/site 를 그대로 씁니다.
dev 와 동시에 플랫폼에 연결하면 같은 edge 로 인식되니 검증은 겹치지 않게 운영합니다.
설치 시 자주 쓰는 env 전체 목록은 env 환경 설정 §6을 봅니다.
4. systemd unit 해부 — plantpulse-edge.service
install.sh 가 /etc/systemd/system/plantpulse-edge.service 로 배치하는 실제 컨테이너 기동 정의입니다.
4.1 docker run (ExecStart)
/usr/bin/docker run --rm --name plantpulse-edge \
--network=host \
--init \
--stop-timeout=120 \
-v /data1:/data1:z \
-v /etc/kopens:/etc/kopens:z \
-v /etc/kopens/conf:/opt/kopens/plantpulse-edge/conf:z \
-v /var/security:/var/security:rw,z \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-e PP_LANG=${PP_LANG} \
-e PP_TZ=${PP_TZ} \
-e CERT_PASS=${CERT_PASS} \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--cap-add=NET_RAW \
--cap-add=DAC_OVERRIDE \
--cap-add=CHOWN \
--cap-add=FOWNER \
--log-driver=journald \
--log-opt tag="plantpulse-edge" \
${KOPENS_IMAGE}:${PE_VERSION}
| 플래그 | 의미 |
|---|---|
--network=host | 9개 포트 자동 노출 + multicast / OPC-UA discovery 자연스러움 |
--init | tini 가 PID 1 (zombie reap + signal forward) |
--stop-timeout=120 | Cassandra graceful drain 시간 확보 |
--cap-drop=ALL + 개별 --cap-add | 최소 권한. NET_RAW 는 PLC ping, NET_BIND_SERVICE 는 80/443 바인드 |
4.2 bind mount
| Host 경로 | 컨테이너 경로 | 모드 | 용도 |
|---|---|---|---|
/data1 | /data1 | rw,z | 데이터 (Cassandra/Redis/HiveMQ/Node-RED) — 컨테이너 교체에도 보존 |
/etc/kopens | /etc/kopens | rw,z | 설정 + 시그널 파일 |
/etc/kopens/conf | /opt/kopens/plantpulse-edge/conf | rw,z | app.properties / log4j2.xml |
/var/security | /var/security | rw,z | TLS keystore |
/etc/localtime | /etc/localtime | ro | 호스트 시간대 |
/var/run/docker.sock | /var/run/docker.sock | rw | /ui/apps 도커 앱 관리 |
4.3 EnvironmentFile + 기본값
unit 내장 기본값(파일 없을 때):
Environment=PE_VERSION=latest
Environment=KOPENS_IMAGE=docker.kopens.io/pe/plantpulse-edge
Environment=PP_LANG=en
Environment=PP_TZ=Asia/Seoul
Environment=CERT_PASS=kopens123!
EnvironmentFile (있으면 override — 최신 값 우선):
| 파일 | 키 | 생성자 |
|---|---|---|
/etc/kopens/version.env | PE_VERSION=<tag> | OTA upgrade.sh |
/etc/kopens/i18n.env | PP_LANG / PP_TZ | install.sh |
/etc/kopens/cert.env | CERT_PASS | TLS 발급 스크립트 |
4.4 자원 한도 / 재시작 정책
MemoryMax=12G # 16GB 박스 기준 — 호스트 OOM 방지
MemoryHigh=11G
CPUQuota=600% # 6 cores
TasksMax=8192
Restart=on-failure
RestartSec=30s
TimeoutStartSec=300
TimeoutStopSec=180
8GB 박스용 heap 축소 override(drop-in)는 컨테이너 모드 §자원 한도를 봅니다.
5. 컨테이너 런타임 설정 읽기 경로
WAR 모드(2026-06-13~)에서 설정은 호스트의 /etc/kopens 에서 직접 읽습니다 — 이미지 재빌드 불필요.
/etc/kopens/app.properties ← 운영자가 편집하는 canonical
│ (entrypoint 가 symlink 생성)
▼
/etc/kopens/conf/app.properties ──bind──▶ /opt/kopens/plantpulse-edge/conf/app.properties
▲
Tomcat setenv.sh: -Dpe.conf.dir=/opt/kopens/plantpulse-edge/conf
- app.properties: 호스트
/etc/kopens/app.properties가 source-of-truth. 없으면 entrypoint 가 image default 로 seed. 운영자 편집 →config.sh --restart로 반영. - log4j2.xml: entrypoint 가 매 부팅 webapp default 에서
conf/log4j2.xml로 복사(코드 산출물 — 이미지 재빌드 없이 로그레벨 변경 후 restart). - HiveMQ auth.properties: entrypoint 가 매 부팅
app.properties의mqtt.server.*와 자동 sync —app.properties만 고치면 됩니다. - TLS 비번: entrypoint 가
CERT_PASS를cert.env에서 해석해 Tomcatserver.xml/ HiveMQ config / OPC-UA keystore 비번을 일괄 패치.
자세한 env→설정 미러링은 환경 변수 설정, 키별 의미는 app.properties 레퍼런스.
6. OTA 업그레이드 / 롤백
버전은 /etc/kopens/version.env 에 고정됩니다 — OTA 가 이 파일을 검증된 다이제스트로 바꾸고 restart.
# 자동 (META-INF/VERSION.JSON 이 가리키는 빌드)
sudo bash /opt/kopens/install/upgrade.sh
# 특정 불변 태그 (YYYY.MM-YYYYMMDD-HHMM). 움직이는 태그는 거부합니다
sudo bash /opt/kopens/install/upgrade.sh --to 2026.11-20261103-1006
# 진행 중인 현재 업그레이드만 롤백 (trial · rollback_failed 상태에서만)
sudo bash /opt/kopens/install/upgrade.sh --rollback
# 사전 점검만 (0 최신, 10 새 빌드 있음)
sudo bash /opt/kopens/install/upgrade.sh --check
상태: cat /etc/kopens/upgrade.status → idle · downloading · verified · snapshot · switching · trial · committed · rolling_back · rolled_back · rollback_failed.
흐름 상세는 업그레이드.
7. 디버그용 수동 docker run
운영은 반드시 systemd / install.sh 경유지만, 격리 디버그 시 수동 기동:
sudo docker run --rm --name pe-debug \
--network=host --init \
-v /data1:/data1:z \
-v /etc/kopens:/etc/kopens:z \
-v /etc/kopens/conf:/opt/kopens/plantpulse-edge/conf:z \
-v /var/security:/var/security:rw,z \
-e PP_LANG=en -e PP_TZ=Asia/Seoul -e CERT_PASS="$(. /etc/kopens/cert.env; echo $CERT_PASS)" \
docker.kopens.io/pe/plantpulse-edge:<tag>
배포는 파이프라인 경유만 — 이미지 (re)build / push / staging 재배포는 로컬에서 하지 말고
plantpulse-edge-docker의 릴리즈 체인(edge:libs→edge:deploy-dev→edge:image→edge:staging→edge:version, 파이프라인 변수RELEASE=1로 트리거)으로 합니다. 위 명령은 격리 디버그 한정.
8. 설치 후 검증
systemctl is-active plantpulse-edge.service
sudo bash /opt/kopens/install/bin/status.sh
# version: container_mode=true 여야 함
curl -ks https://127.0.0.1/api/v1/system/version | python3 -m json.tool
# health: HTTP 200 + components UP
curl -ks https://127.0.0.1/api/v1/system/health | python3 -m json.tool
| 화면 | URL |
|---|---|
| 웹 UI | https://<게이트웨이-IP>/ui/main |
| Node-RED | https://<게이트웨이-IP>/ui/flow/ |
| Swagger UI | https://<게이트웨이-IP>/public/swagger-ui/index.html |
증상별 조치는 설치 문제 해결, 일상 운영/장애는 컨테이너 모드 운영.
9. 다음 문서
- 빠른 설치 (
install.sh) — 현장 1대 설치 절차 요약 - 환경 변수 설정 —
PROFILE/PP_LANG/CERT_PASS/-Dpe.conf.dir - 컨테이너 모드 운영 — pe-* 도구 / 로그 / 장애 대응
- 폐쇄망 설치 / 양산 라인 (
factory.sh) - 프로덕션 인수 기준