You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker-Compose启动时Entrypoint.sh中数据库迁移未执行问题

问题描述

我是Docker新手,正在将基于Symfony API和MySQL数据库的项目容器化。希望容器启动时自动执行数据库迁移命令php bin/console doctrine:migrations:migrate,于是添加了Entrypoint脚本:

entrypoint.sh

#create or update db
php bin/console doctrine:migrations:migrate --no-interaction

# start apache
apache2-foreground

执行docker-compose up -d后,容器看似正常启动,但数据库未完成迁移。进入容器手动执行doc:mig:mig命令却能成功,请问如何实现自动执行?是不是我对Entrypoint的用法理解有误?

以下是我的配置文件:

docker-compose.yaml(敏感信息已替换)

version: '3.7'
services:
    api:
        build: .
        ports:
            - 8000:80
        links:
            - db
        volumes:
            - C:/Repos/myProjectName/src:/var/www/myProjectName_api/src
    db:
        image: 'mysql:8.0'
        container_name: mysql
        environment:
            MYSQL_USER: myUserName
            MYSQL_PASSWORD: myPwd
            MYSQL_ROOT_PASSWORD: myRootPwd
            MYSQL_DATABASE: dev_myProjectName
        volumes:
            - ./mysql:/var/lib/mysql
        command: ["--default-authentication-plugin=mysql_native_password"]
        ports:
            - "3307:3306"

Dockerfile

FROM php:8.1-apache

RUN a2enmod rewrite
RUN apt-get update \
  && apt-get install -y libzip-dev git wget nano --no-install-recommends \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install zip

RUN wget https://getcomposer.org/download/2.4.2/composer.phar \
    && mv composer.phar /usr/bin/composer && chmod +x /usr/bin/composer
COPY docker/apache.conf /etc/apache2/sites-enabled/000-default.conf
COPY . /var/www/myProjectName_api

RUN chown -R www-data:www-data /var/www/myProjectName_api/var

# Allow Authorization header
RUN echo 'SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1' >> /etc/apache2/apache2.conf

COPY environments/.env.dev /var/www/myProjectName_api/.env.local

WORKDIR /var/www/myProjectName_api

COPY docker/entrypoint.sh /tmp
RUN chmod +x /tmp/entrypoint.sh
ENTRYPOINT /tmp/entrypoint.sh
解决方案

你的问题核心是API容器启动时,MySQL容器还没完全就绪,导致迁移命令执行失败;另外Entrypoint的写法也有可优化的地方。

1. 添加数据库就绪等待逻辑

Docker的links或depends_on仅保证容器启动顺序,不会等待数据库服务完全可用。需要在entrypoint脚本里添加等待数据库就绪的判断:

修改entrypoint.sh:

#!/bin/bash

# 等待MySQL数据库就绪
wait_for_db() {
    until php bin/console doctrine:query:sql "SELECT 1" > /dev/null 2>&1; do
        echo "等待MySQL数据库就绪..."
        sleep 2
    done
    echo "数据库已就绪,开始执行迁移..."
}

wait_for_db

# 执行数据库迁移
php bin/console doctrine:migrations:migrate --no-interaction

# 用exec启动apache,让它成为容器PID 1进程(保证信号正确传递)
exec apache2-foreground

2. 优化Entrypoint脚本规范

  • 脚本开头添加#!/bin/bash,明确指定shell解释器,避免环境兼容问题
  • 最后启动apache时使用exec,让apache取代entrypoint脚本成为容器主进程,确保容器能正确响应docker stop等停止信号

3. 完善docker-compose配置

将links: - db替换为depends_on: - db,这是Docker Compose推荐的服务依赖写法:

services:
    api:
        build: .
        ports:
            - 8000:80
        depends_on:
            - db
        volumes:
            - C:/Repos/myProjectName/src:/var/www/myProjectName_api/src

4. 验证修改效果

  1. 重新构建镜像:docker-compose build
  2. 启动容器:docker-compose up -d
  3. 查看API容器日志:docker-compose logs api,确认能看到"数据库已就绪,开始执行迁移..."的日志,以及迁移成功的输出

额外注意事项

  • 当前Dockerfile未执行composer install,如果项目依赖Composer包,需要添加RUN composer install --no-dev --optimize-autoloader命令
  • 挂载的src卷可能覆盖容器内文件,确保迁移文件已存在于容器内或挂载的卷中

内容的提问来源于stack exchange,提问作者Diplodoco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:05:22