Docker部署应用时数据库表未创建,新手求助排查操作问题
Hey there! Let's break down why your database tables aren't showing up and fix this step by step.
The Core Problem
You're hitting two main issues here:
- Wrong initialization directory: The
/docker-entrypoint-initdb.d/folder is a feature of official MySQL/MariaDB Docker images—not thephp:7.1-apacheimage you're using. The PHP-Apache image has no logic to run SQL files from that directory, so yourdump.sqlis just sitting there unused. - Missing database service: Your docker-compose.yml only defines your PHP app service, but there's no actual MySQL/MariaDB container running for your app to connect to. No database = no tables to create!
Fixes to Apply
1. Add a MySQL Service to docker-compose.yml
First, we need to spin up a MySQL container and tell it to run your dump.sql on startup. Here's an updated version of your docker-compose.yml:
version: '2' volumes: logs: driver: local db_data: # Persists MySQL data so it doesn't get lost when the container restarts driver: local services: slim: build: . working_dir: /var/www # Update this command to match your app's actual server start command command: php -S 0.0.0.0:8000 -t public ports: - "8080:8000" # Maps your host port 8080 to the app's port 8000 depends_on: - mysql # Ensures the database starts before your app environment: # Set these values to match your app's database config DB_HOST: mysql DB_PORT: 3306 DB_NAME: my_app_db DB_USER: root DB_PASSWORD: my_secure_password mysql: # Use a MySQL version compatible with PHP 7.1 (5.7 works well) image: mysql:5.7 volumes: # Mount your dump.sql into MySQL's official init directory - ./dump.sql:/docker-entrypoint-initdb.d/dump.sql - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: my_secure_password MYSQL_DATABASE: my_app_db # Automatically creates this database for you
2. Update Your App's Database Connection
Make sure your application's database config uses the environment variables we set above. For example, if you're using Slim, your config might look like this:
$settings['db'] = [ 'host' => getenv('DB_HOST'), 'port' => getenv('DB_PORT'), 'database' => getenv('DB_NAME'), 'username' => getenv('DB_USER'), 'password' => getenv('DB_PASSWORD'), ];
3. Optional: Add a Wait Script (Avoid Race Conditions)
Sometimes your app might start before MySQL is fully initialized. To fix this, you can add a script to wait for the database to be ready:
Update your Dockerfile to install the wait-for-it script:
FROM php:7.1-apache RUN docker-php-ext-install pdo pdo_mysql # Install wait-for-it to wait for MySQL RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/* RUN wget -O /usr/local/bin/wait-for-it https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh RUN chmod +x /usr/local/bin/wait-for-it
Then modify the command in your slim service to use it:
command: wait-for-it mysql:3306 -- php -S 0.0.0.0:8000 -t public
Final Notes
- When you start the stack with
docker-compose up --build, MySQL will automatically run yourdump.sqlinside themy_app_dbdatabase we defined. - The
db_datavolume ensures your database data persists even if you stop and restart the containers.
Give this setup a try, and your tables should be created correctly now!
内容的提问来源于stack exchange,提问作者Schnecke

