GitLab Runner 中的 Docker Compose 容器崩溃 - 无写入访问权限

问题描述 投票:0回答:1

我在 GitLab 设置中使用 Docker 运行程序来为我的应用程序测试构建 Docker 映像。该图像是一个带有一些预配置设置的 Keycloak 容器。

我创建了一个使用 Docker Compose 的

build.sh
脚本。我用
- ./data:/opt/keycloak/data/
挂载 Keycloak 数据目录。但是,当我启动容器时,容器因错误而崩溃。

管道步骤

build-keycloak-test-image:
  stage: build-keycloak-test-image
  before_script:
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
    - apk add --no-cache curl
    - chmod +x ./keycloak/test/build.sh
  script:
    - cd ./keycloak/test/
    - sh ./build.sh
    - docker push $KEYCLOAK_TEST_IMAGE
  only:
    - tags

构建脚本

#!/bin/bash
KEYCLOAK_URL="${KEYCLOAK_TEST_GEN_URL:-http://localhost:8889}"
# Endpoint to be checked
HEALTH_ENDPOINT="/health"

rm -fr ./data/*
mkdir ./data
chmod -R 777 ./data/
docker compose up -d
# ...

日志

以下是启动容器后的一些日志:

2024-09-13 15:07:03,053 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: token-exchange
2024-09-13 15:07:12,589 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 10289ms
2024-09-13 15:07:13,837 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: token-exchange
2024-09-13 15:07:14,520 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: <unset>, Hostname: <request>, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin URL: <unset>, Admin: <request>, Port: -1, Proxied: false
2024-09-13 15:07:17,244 WARN  [io.quarkus.agroal.runtime.DataSources] (main) Datasource <default> enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2024-09-13 15:07:17,928 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2024-09-13 15:07:17,966 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2024-09-13 15:07:18,052 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
org.h2.message.DbException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
org.h2.message.DbException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
    at org.h2.message.DbException.get(DbException.java:212)
    at org.h2.message.TraceSystem.logWritingError(TraceSystem.java:327)
    at org.h2.message.TraceSystem.openWriter(TraceSystem.java:348)
    at org.h2.message.TraceSystem.writeFile(TraceSystem.java:296)
    at org.h2.message.TraceSystem.write(TraceSystem.java:280)
    at org.h2.message.Trace.error(Trace.java:187)
    at org.h2.engine.Database.<init>(Database.java:397)
    at org.h2.engine.Engine.openSession(Engine.java:92)
    at org.h2.engine.Engine.openSession(Engine.java:222)
    at org.h2.engine.Engine.createSession(Engine.java:201)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:125)
    at org.h2.jdbcx.JdbcDataSource.getXAConnection(JdbcDataSource.java:322)
    at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:536)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:517)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
    ... 21 more
Caused by: org.h2.message.DbException: Error while creating file "/opt/keycloak/data/h2" [90062-224]
    at org.h2.message.DbException.get(DbException.java:212)
    at org.h2.store.fs.disk.FilePathDisk.createDirectory(FilePathDisk.java:391)
    at org.h2.store.fs.FileUtils.createDirectory(FileUtils.java:85)
    at org.h2.store.fs.FileUtils.createDirectories(FileUtils.java:382)
    at org.h2.message.TraceSystem.openWriter(TraceSystem.java:338)
    ... 18 more
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Error while creating file "/opt/keycloak/data/h2" [90062-224]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
    ... 23 more
Caused by: java.nio.file.AccessDeniedException: /opt/keycloak/data/h2
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:397)
    at java.base/java.nio.file.Files.createDirectory(Files.java:700)
    at org.h2.store.fs.disk.FilePathDisk.createDirectory(FilePathDisk.java:382)
    ... 21 more
2024-09-13 15:07:20,174 WARN  [io.agroal.pool] (agroal-11) Datasource '<default>': Error while creating file "/opt/keycloak/data/h2" [90062-224]
2024-09-13 15:07:20,177 WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread) HHH000342: Could not obtain connection to query metadata: java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.sqlExceptionHelper()" is null
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doTheWork(JtaIsolationDelegate.java:186)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.lambda$delegateWork$1(JtaIsolationDelegate.java:75)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doInSuspendedTransaction(JtaIsolationDelegate.java:107)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.delegateWork(JtaIsolationDelegate.java:72)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:279)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:193)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:69)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:239)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:52)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:125)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:248)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216)
    at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.<init>(SessionFactoryOptionsBuilder.java:273)
    at io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata.buildSessionFactoryOptionsBuilder(PrevalidatedQuarkusMetadata.java:70)
    at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:81)
    at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:74)
    at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
    at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:156)
    at io.quarkus.hibernate.orm.runtime.JPAConfig$1.run(JPAConfig.java:64)
    at java.base/java.lang.Thread.run(Thread.java:840)

2024-09-13 15:07:21,152 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_491456, Site name: null
org.h2.message.DbException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
org.h2.message.DbException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
    at org.h2.message.DbException.get(DbException.java:212)
    at org.h2.message.TraceSystem.logWritingError(TraceSystem.java:327)
    at org.h2.message.TraceSystem.openWriter(TraceSystem.java:348)
    at org.h2.message.TraceSystem.writeFile(TraceSystem.java:296)
    at org.h2.message.TraceSystem.write(TraceSystem.java:280)
    at org.h2.message.Trace.error(Trace.java:187)
    at org.h2.engine.Database.<init>(Database.java:397)
    at org.h2.engine.Engine.openSession(Engine.java:92)
    at org.h2.engine.Engine.openSession(Engine.java:222)
    at org.h2.engine.Engine.createSession(Engine.java:201)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:125)
    at org.h2.jdbcx.JdbcDataSource.getXAConnection(JdbcDataSource.java:322)
    at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:536)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:517)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Log file error: "/opt/keycloak/data/h2/keycloakdb.trace.db", cause: "org.h2.message.DbException: Error while creating file ""/opt/keycloak/data/h2"" [90062-224]" [90034-224]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
    ... 21 more
Caused by: org.h2.message.DbException: Error while creating file "/opt/keycloak/data/h2" [90062-224]
    at org.h2.message.DbException.get(DbException.java:212)
    at org.h2.store.fs.disk.FilePathDisk.createDirectory(FilePathDisk.java:391)
    at org.h2.store.fs.FileUtils.createDirectory(FileUtils.java:85)
    at org.h2.store.fs.FileUtils.createDirectories(FileUtils.java:382)
    at org.h2.message.TraceSystem.openWriter(TraceSystem.java:338)
    ... 18 more
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Error while creating file "/opt/keycloak/data/h2" [90062-224]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
    ... 23 more
Caused by: java.nio.file.AccessDeniedException: /opt/keycloak/data/h2
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:397)
    at java.base/java.nio.file.Files.createDirectory(Files.java:700)
    at org.h2.store.fs.disk.FilePathDisk.createDirectory(FilePathDisk.java:382)
    ... 21 more
2024-09-13 15:07:23,831 WARN  [io.agroal.pool] (agroal-11) Datasource '<default>': Error while creating file "/opt/keycloak/data/h2" [90062-224]
2024-09-13 15:07:23,908 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
2024-09-13 15:07:23,909 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to obtain JDBC connection
2024-09-13 15:07:23,910 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Error while creating file "/opt/keycloak/data/h2" [90062-224]
2024-09-13 15:07:23,910 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: /opt/keycloak/data/h2
2024-09-13 15:07:23,912 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.

Docker 撰写文件

services:
  keycloak:
    image: quay.io/keycloak/keycloak:23.0.6
    ports:
      - "8889:8080"
    command:
      - start-dev
    volumes:
      - ./data:/opt/keycloak/data/
    environment:
      KEYCLOAK_ADMIN: "admin"
      KEYCLOAK_ADMIN_PASSWORD: "mypass"
      KC_HEALTH_ENABLED: true
      KC_METRICS_ENABLED: true
      KC_HOSTNAME_STRICT: false
      KC_HTTP_ENABLED: false
      KC_FEATURES: "token-exchange"
      PROXY_ADDRESS_FORWARDING: true
    networks:
      - gitlab
      - default
networks:
  gitlab:
    name: gitlab-network

观察结果

我的脚本应该创建数据目录并将权限设置为 777,因此任何进程都应该写入该目录。我检查了容器内部:

# ls /builds/dev/project/keycloak/test/ -lah
total 24K
drwxrwxrwx    3 root     root        4.0K Sep 13 15:06 .
drwxrwxrwx    7 root     root        4.0K Sep  4 12:56 ..
...
drwxrwxrwx    2 root     root        4.0K Sep 13 15:06 data

在我的本地机器上一切正常,但容器在 GitLab 环境中失败。

问题

有谁知道为什么 Docker 容器会因这些错误而崩溃?任何帮助将不胜感激!

T

docker gitlab gitlab-ci-runner cicd runner
1个回答
0
投票

此错误的原因是在运行的容器中当前用户是keyckloak:

uid=1000(keycloak) gid=0(root) groups=0(root)

但是目录

/opt/keycloak/data/
正在创建,但具有 root 限制并且没有组的写入权限:

drwxr-xr-x 2 root root 4.0K 10 月 31 日 19:21 /opt/keycloak/data/

您所做的权限检查 (

ls /builds/dev/project/keycloak/test/ -lah
) 显然不在容器内部,而是在 GitLab 工作的范围内(您在其中启动了 build.sh,为 ./data/ 目录提供了完全权限)。 要检查容器内的实际目录权限,您可以临时将 docker-compose 文件中的“command”指令替换为以下指令:

入口点:[“ls”,“-lshd”,“/opt/keycloak/data/”]

此处的解决方法之一可能是使当前用户成为容器内的 root,将

user: root
指令添加到 docker compose 文件中:

services:
  keycloak:
    image: quay.io/keycloak/keycloak:23.0.6
    user: root
...

第二个选项是在 docker compose 中创建传递服务,该服务将为已安装的卷预先设置适当的所有者,如下所述:

或者最终构建一个扩展 keycloak 的自定义镜像,并在镜像构建阶段执行所有这些权限操作。

© www.soinside.com 2019 - 2024. All rights reserved.