docker compose up -d 로 올린 trinodb/trino 컨테이너가 바로 죽는다. docker compose ps 에 Exit 1 또는 Exit 100 만 남고, 원인은 docker compose logs trino 의 첫 오류 줄에 있다. 증상별로 원인이 완전히 다르므로 로그를 먼저 읽고 아래에서 해당 절을 찾는다.
ERROR: JVM config file is missing: could not find file: /etc/trino/jvm.config
컨테이너는 설정을 /etc/trino 바로 아래에서 찾는다. 호스트의 ./etc 를 /etc/trino 에 마운트했는데 파일을 ./etc/trino/ 안에 두면 컨테이너에서는 /etc/trino/trino/jvm.config 가 되어 찾지 못한다. 마운트 소스와 파일 위치 중 하나를 맞춘다.
services:
trino:
image: trinodb/trino:483
volumes:
- ./etc:/etc/trino
이 구성이면 ./etc/jvm.config · ./etc/config.properties · ./etc/node.properties · ./etc/catalog/*.properties 가 된다. 마운트한 뒤 실제로 무엇이 보이는지 확인한다.
docker exec -it trino ls -l /etc/trino
SELinux 가 Enforcing 인 RHEL 계열에서는 볼륨에 :Z 를 붙여야 컨테이너가 읽을 수 있다.
volumes:
- ./etc:/etc/trino:Z
ERROR: could not exec java to determine jvm version: exit status 1
컨테이너 안에서 java 자체가 실행되지 못한 것이다. 이미지 하나만으로 재현되는지 먼저 가른다.
docker run --rm trinodb/trino:483 java -version
여기서도 실패하면 Trino 설정과 무관하다. 아래 pthread_create failed (EPERM) 절을 본다. 이 명령이 정상이라면 compose 의 JAVA_HOME · PATH 를 덮어쓴 환경변수가 원인이므로 지운다. 이미지는 자체 JRE 경로를 쓴다. ARM 호스트에서 amd64 이미지를 받은 경우에는 platform: linux/amd64 를 명시한다.
[warning][os,thread] Failed to start thread "GC Thread#0" - pthread_create failed (EPERM)
[error ][gc,task ] Failed to create worker thread
JVM 이 스레드를 만들지 못한다. 원인은 둘 중 하나다.
첫째, PID·스레드 제한이다. 먼저 제한을 풀고 재현되는지 본다.
docker run --rm \
--pids-limit 0 \
--ulimit nproc=65535:65535 \
--ulimit nofile=1048576:1048576 \
trinodb/trino:483 java -version
여기서 성공하면 compose 에 같은 값을 넣는다. Docker 데몬 자체가 TasksMax 로 묶여 있으면 컨테이너도 따라 묶이므로 systemctl show docker | grep TasksMax 도 함께 본다.
pids_limit: 0
ulimits:
nproc: 65535
nofile:
soft: 1048576
hard: 1048576
둘째, seccomp 다. 위 조치로도 같은 오류가 나면 seccomp 프로파일이 clone3 시스템 콜을 막고 있는 경우다. 최신 JDK 는 스레드 생성에 clone3 를 쓰는데, 오래된 Docker·runc 에 들어 있는 기본 seccomp 프로파일에는 clone3 허용이 없어 EPERM 이 난다.
docker run --rm --security-opt seccomp=unconfined trinodb/trino:483 java -version
이것으로 뜨면 원인이 확정된다. 다만 seccomp=unconfined 는 컨테이너의 시스템 콜 제한을 통째로 푸는 것이라 진단·개발용으로만 쓴다. 근본 해결은 Docker·containerd·runc 를 올려 clone3 가 허용된 기본 프로파일을 받는 것이고, 올릴 수 없으면 clone3 만 SCMP_ACT_ALLOW 로 추가한 커스텀 프로파일을 만들어 --security-opt seccomp=/path/seccomp.json 으로 지정한다.
1) Configuration property 'discovery-server.enabled' was not used
Trino 는 인식하지 못한 설정 키가 있으면 기동을 거부한다. discovery-server.enabled 는 옛 키이고 현행에서는 코디네이터가 자동으로 discovery 역할을 하므로 config.properties 에서 그 줄을 지운다.
coordinator=true
node-scheduler.include-coordinator=true
http-server.http.port=8080
discovery.uri=http://trino-coordinator:8080
Windows 편집기로 만든 파일이면 CRLF 도 같은 증상을 일으키므로 dos2unix 로 확인한다. 멀티 노드면 discovery.uri 는 코디네이터 주소여야 한다.
compose 파일에 command: 나 entrypoint: 가 빈 값으로 들어가면 이미지의 기본 실행 명령이 지워져 컨테이너가 만들어지다 실패한다. 병합된 최종 설정을 확인한다.
docker compose config
docker image inspect trinodb/trino:483 -f 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'
command: "" · command: [] · 값 없는 command: · command: ${CMD} (미정의 변수) 같은 줄이 있으면 지운다. Trino 이미지는 기본 실행 명령을 스스로 갖고 있으므로 넣을 이유가 없다.
ports 의 표기는 호스트포트:컨테이너포트 다. config.properties 에서 http-server.http.port 를 바꿨다면 오른쪽 값이 그 포트여야 한다.
ports:
- "48080:48080"
외부는 8080 으로 두고 내부만 48080 으로 쓰려면 "8080:48080" 이다. 정상 기동하면 로그에 ======== SERVER STARTED ======== 가 찍힌다.
Trino 설치 · Trino 설정 · Kubernetes 위 Trino 기동 문제