本文最后更新于 2026年5月11日。
mariadb创建数据库 biblioteca
最终编排
services:
biblioteca:
image: ghcr.io/biblioverse/biblioteca:main
container_name: biblioteca
networks:
- 1panel-network
command: ["/bin/sh", "-c" , "apache2-foreground" ]
# ports:
# - 8080
# depends_on:
# - db
stdin_open: true
tty: true
restart: unless-stopped
volumes:
- /share/dockermnt/biblioteca/covers:/var/www/html/public/covers
- /share/dockermnt/biblioteca/books:/var/www/html/public/books
- /share/dockermnt/biblioteca/media:/var/www/html/public/media
# - /share/dockermnt/biblioteca/.env:/var/www/html/.env
environment:
- APP_SECRET=biblioteca_secret
- DATABASE_URL=mysql://bibliotecauser:BtrXKFGcYcPfG2Z4@mariadb:3306/biblioteca
- TYPESENSE_KEY=xyz123
typesense:
image: docker.1ms.run/typesense/typesense:29.0
container_name: typesense
restart: unless-stopped
# ports:
# - 8983
# - 8108
volumes:
- /share/dockerdata/typesense/data:/data
command: '--data-dir /data --api-key=xyz123 --enable-cors'
networks:
- 1panel-network
networks:
1panel-network:
external: true
搭建biblioteca后访问http://172.29.0.15/提示连接被重置,日志:
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message [Mon Sep 29 07:11:08.572393 2025] [mpm_prefork:notice] [pid 7:tid 7] AH00163: Apache/2.4.62 (Debian) PHP/8.3.16 configured -- resuming normal operations [Mon Sep 29 07:11:08.572454 2025] [core:notice] [pid 7:tid 7] AH00094: Command line: 'apache2 -D FOREGROUND'
只提示域名信息
进入容器能查到具体信息,看来是有默认映射,并且默认的已经被占用了
$ apache2-foreground
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:8080
no listening sockets available, shutting down
AH00015: Unable to open logs
$
所以编排要显示指定映射,还是不行
查看容器里边原来是apache2配置的问题
$ cat /etc/apache2/ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf
Listen 8080
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
$
教程还有后续步骤
Run the following commands to create the database and the admin user:
docker compose exec biblioteca bin/console doctrine:migration:migrate --no-interactiondocker compose exec biblioteca
bin/console app:create-admin-user [name] [password]
docker compose exec biblioteca bin/console biblioverse:typesense:populate
我实际执行
docker compose exec biblioteca bin/console doctrine:migration:migrate --no-interaction
docker compose exec biblioteca bin/console app:create-admin-user wyty wytyfu=321
docker compose exec biblioteca bin/console biblioverse:typesense:populate
操作日志(缓存部分失败)
$ bin/console doctrine:migration:migrate --no-interaction
[notice] Migrating up to DoctrineMigrations\Version20250404084822
[warning] Migration DoctrineMigrations\Version20240531124659 was executed but did not result in any SQL statements.
[notice] finished in 21225.8ms, used 16M memory, 37 migrations executed, 92 sql queries
[OK] Successfully migrated to version: DoctrineMigrations\Version20250404084822
$ bin/console app:create-admin-user wyty wytyfu=321
[OK] User created
$ bin/console biblioverse:typesense:populate
Creating collection books-2025-09-29-07-59-48
07:59:51 CRITICAL [console] Error thrown while running command "biblioverse:typesense:populate". Message: "Unable to create collection" ["exception" => RuntimeException { …},"command" => "biblioverse:typesense:populate","message" => "Unable to create collection"]
In PopulateService.php line 44:
Unable to create collection
In ApiCall.php line 372:
Model not found
biblioverse:typesense:populate [--no-data] [--nb-retry NB-RETRY]
$
创建查询失败
尝试访问 Typesense API
curl http://typesense:8108/health -H "X-TYPESENSE-API-Key: xyz"
curl http://172.29.0.14:8108/health -H "X-TYPESENSE-API-Key: xyz123"
返回ok
[weiyoun@WeiyounNAS ~]$ curl http://172.29.0.14:8108/health -H "X-TYPESENSE-API-Key: xyz123"
{"ok":true}
浏览器直接访问 http://172.29.0.14:8108/health 也行
提交书籍时出现具体错误堆栈
# An error happend
## 500 Internal Server Error
### Collection not found
Stack trace#0 /var/www/html/vendor/typesense/typesense-php/src/ApiCall.php(261): Typesense\ApiCall->getException(404) #1 /var/www/html/vendor/typesense/typesense-php/src/ApiCall.php(125): Typesense\ApiCall->makeRequest('post', '/collections/bo...', true, Array) #2 /var/www/html/vendor/typesense/typesense-php/src/Documents.php(83): Typesense\ApiCall->post('/collections/bo...', Array, true, Array) #3 /var/www/html/vendor/biblioverse/typesense-bundle/src/Populate/PopulateService.php(69): Typesense\Documents->upsert(Array) #4 /var/www/html/vendor/biblioverse/typesense-bundle/src/EventSubscriber/IndexCollectionSubscriber.php(81): Biblioverse\TypesenseBundle\Populate\PopulateService->fillData('books', Array) #5 /var/www/html/vendor/biblioverse/typesense-bundle/src/EventSubscriber/IndexCollectionSubscriber.php(36): Biblioverse\TypesenseBundle\EventSubscriber\IndexCollectionSubscriber->indexEntity(Object(App\Entity\Book)) #6 /var/www/html/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php(56): Biblioverse\TypesenseBundle\EventSubscriber\IndexCollectionSubscriber->postFlush(Object(Doctrine\ORM\Event\PostFlushEventArgs)) #7 /var/www/html/vendor/doctrine/orm/src/UnitOfWork.php(3153): Symfony\Bridge\Doctrine\ContainerAwareEventManager->dispatchEvent('postFlush', Object(Doctrine\ORM\Event\PostFlushEventArgs)) #8 /var/www/html/vendor/doctrine/orm/src/UnitOfWork.php(470): Doctrine\ORM\UnitOfWork->dispatchPostFlushEvent() #9 /var/www/html/vendor/doctrine/orm/src/EntityManager.php(268): Doctrine\ORM\UnitOfWork->commit() #10 /var/www/html/src/Service/BookManager.php(212): Doctrine\ORM\EntityManager->flush() #11 /var/www/html/src/Controller/BookController.php(385): App\Service\BookManager->save(Object(App\Entity\Book)) #12 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(183): App\Controller\BookController->consume(Object(Symfony\Component\HttpFoundation\Request), Object(App\Service\BookFileSystemManager)) #13 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #14 /var/www/html/vendor/symfony/http-kernel/Kernel.php(182): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #15 /var/www/html/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php(86): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #16 /var/www/html/vendor/symfony/http-kernel/HttpCache/HttpCache.php(466): Symfony\Component\HttpKernel\HttpCache\SubRequestHandler::handle(Object(App\Kernel), Object(Symfony\Component\HttpFoundation\Request), 1, true) #17 /var/www/html/vendor/symfony/framework-bundle/HttpCache/HttpCache.php(68): Symfony\Component\HttpKernel\HttpCache\HttpCache->forward(Object(Symfony\Component\HttpFoundation\Request), true, NULL) #18 /var/www/html/vendor/symfony/http-kernel/HttpCache/HttpCache.php(443): Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache->forward(Object(Symfony\Component\HttpFoundation\Request), true) #19 /var/www/html/vendor/symfony/http-kernel/HttpCache/HttpCache.php(341): Symfony\Component\HttpKernel\HttpCache\HttpCache->fetch(Object(Symfony\Component\HttpFoundation\Request), true) #20 /var/www/html/vendor/symfony/http-kernel/HttpCache/HttpCache.php(216): Symfony\Component\HttpKernel\HttpCache\HttpCache->lookup(Object(Symfony\Component\HttpFoundation\Request), true) #21 /var/www/html/vendor/symfony/http-kernel/Kernel.php(173): Symfony\Component\HttpKernel\HttpCache\HttpCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /var/www/html/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php(35): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #23 /var/www/html/vendor/autoload_runtime.php(29): Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() #24 /var/www/html/public/index.php(5): require_once('/var/www/html/v...') #25 {main}
手动创建 books 集合
使用 Typesense 的 API 创建集合:
curl -X POST 'http://172.29.0.14:8108/collections' \
-H 'Content-Type: application/json' \
-H "X-TYPESENSE-API-Key: xyz123" \
-d '{
"name": "books",
"fields": [
{"name": "title", "type": "string"},
{"name": "author", "type": "string"},
{"name": "publication_year", "type": "int32"},
{"name": "tags", "type": "string[]", "optional": true},
{"name": "isbn", "type": "string", "optional": true},
{"name": "publisher", "type": "string", "optional": true},
{"name": "language", "type": "string", "optional": true}
],
"default_sorting_field": "publication_year"
}'
日志
[weiyoun@WeiyounNAS ~]$ curl -X POST 'http://172.29.0.14:8108/collections' \
> -H 'Content-Type: application/json' \
> -H "X-TYPESENSE-API-Key: xyz123" \
> -d '{
> "name": "books",
> "fields": [
> {"name": "title", "type": "string"},
> {"name": "author", "type": "string"},
> {"name": "publication_year", "type": "int32"},
> {"name": "tags", "type": "string[]", "optional": true},
> {"name": "isbn", "type": "string", "optional": true},
> {"name": "publisher", "type": "string", "optional": true},
> {"name": "language", "type": "string", "optional": true}
> ],
> "default_sorting_field": "publication_year"
> }'
{"created_at":1759135266,"default_sorting_field":"publication_year","enable_nested_fields":false,"fields":[{"facet":false,"index":true,"infix":false,"locale":"","name":"title","optional":false,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string"},{"facet":false,"index":true,"infix":false,"locale":"","name":"author","optional":false,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string"},{"facet":false,"index":true,"infix":false,"locale":"","name":"publication_year","optional":false,"sort":true,"stem":false,"stem_dictionary":"","store":true,"type":"int32"},{"facet":false,"index":true,"infix":false,"locale":"","name":"tags","optional":true,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string[]"},{"facet":false,"index":true,"infix":false,"locale":"","name":"isbn","optional":true,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string"},{"facet":false,"index":true,"infix":false,"locale":"","name":"publisher","optional":true,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string"},{"facet":false,"index":true,"infix":false,"locale":"","name":"language","optional":true,"sort":false,"stem":false,"stem_dictionary":"","store":true,"type":"string"}],"name":"books","num_documents":0,"symbols_to_index":[],"token_separators":[]}[weiyoun@WeiyounNAS ~]$
确认集合已经创建成功:
curl 'http://172.29.0.14:8108/collections/books' -H "X-TYPESENSE-API-Key: xyz123"
访问成功
http://172.29.0.15:8080/
问题是这个镜像做的不好,镜像暴露80端口,实际是要访问8080端口
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message
[Mon Sep 29 07:34:08.560991 2025] [mpm_prefork:notice] [pid 6:tid 6] AH00163: Apache/2.4.62 (Debian) PHP/8.3.16 configured -- resuming normal operations
[Mon Sep 29 07:34:08.561055 2025] [core:notice] [pid 6:tid 6] AH00094: Command line: 'apache2 -D FOREGROUND'
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.29.0.15. Set the 'ServerName' directive globally to suppress this message
[Mon Sep 29 07:52:16.850381 2025] [mpm_prefork:notice] [pid 8:tid 8] AH00163: Apache/2.4.62 (Debian) PHP/8.3.16 configured -- resuming normal operations
[Mon Sep 29 07:52:16.850866 2025] [core:notice] [pid 8:tid 8] AH00094: Command line: 'apache2 -D FOREGROUND'
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET / HTTP/1.1" 302 848 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /login HTTP/1.1" 200 1333 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /build/682.572c4e34.css HTTP/1.1" 200 17472 "http://172.29.0.15:8080/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /build/app.a9a294ff.css HTTP/1.1" 200 33519 "http://172.29.0.15:8080/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /build/runtime.ef24c45b.js HTTP/1.1" 200 1845 "http://172.29.0.15:8080/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /build/203.8bd647f2.js HTTP/1.1" 200 12953 "http://172.29.0.15:8080/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 172.29.0.1 - - [29/Sep/2025:08:00:51 +0000] "GET /build/login.e2d16856.js HTTP/1.1" 200 7645 "http://172.29.0.15:8080/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
172.29.0.15:8080 127.0.0.1 - - [29/Sep/2025:08:00:59 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.62 (Debian) PHP/8.3.16 (internal dummy connection)"
172.29.0.15:8080 127.0.0.1 - - [29/Sep/2025:08:01:00 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.62 (Debi