admin管理员组

文章数量:1200790

I have a project developed with PHP and I want to move it inside a Docker container. I want to import database automatically inside Dockerfile.

If I import the database after building the container all works fine (docker exec -it my-laravel-app bash then mysql -u user -p1993 -h db bsp < /var/www/database/bsp.sql).

I get the error failed to solve: process "/bin/sh -c wait-for-it -t 30 ${DB_HOST}:${DB_PORT} if [ -f /var/www/database/bsp.sql ]; then mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; fi" did not complete successfully: exit code: 2.

Dockerfile

# Set the base image for subsequent instructions
FROM php:8.2-fpm

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    curl \
    unzip \
    git \
    libzip-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    default-mysql-client \
    wait-for-it \
    libpng-dev && \
    docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www

# Remove default server definition
RUN rm -rf /var/www/html

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www

# Change current user to www
USER www-data

ENV DB_HOST=db
ENV DB_PORT=3306
ENV DB_DATABASE=bsp
ENV DB_USERNAME=user
ENV DB_PASSWORD=1993

# Wait for the database to be ready and import SQL dump
USER root
RUN wait-for-it -t 30 ${DB_HOST}:${DB_PORT} \
if [ -f /var/www/database/bsp.sql ]; then \
    mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; \
fi
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

I have a project developed with PHP and I want to move it inside a Docker container. I want to import database automatically inside Dockerfile.

If I import the database after building the container all works fine (docker exec -it my-laravel-app bash then mysql -u user -p1993 -h db bsp < /var/www/database/bsp.sql).

I get the error failed to solve: process "/bin/sh -c wait-for-it -t 30 ${DB_HOST}:${DB_PORT} if [ -f /var/www/database/bsp.sql ]; then mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; fi" did not complete successfully: exit code: 2.

Dockerfile

# Set the base image for subsequent instructions
FROM php:8.2-fpm

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    curl \
    unzip \
    git \
    libzip-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    default-mysql-client \
    wait-for-it \
    libpng-dev && \
    docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www

# Remove default server definition
RUN rm -rf /var/www/html

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www

# Change current user to www
USER www-data

ENV DB_HOST=db
ENV DB_PORT=3306
ENV DB_DATABASE=bsp
ENV DB_USERNAME=user
ENV DB_PASSWORD=1993

# Wait for the database to be ready and import SQL dump
USER root
RUN wait-for-it -t 30 ${DB_HOST}:${DB_PORT} \
if [ -f /var/www/database/bsp.sql ]; then \
    mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; \
fi
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
Share Improve this question edited Jan 21 at 15:47 hakre 198k55 gold badges446 silver badges854 bronze badges Recognized by PHP Collective asked Jan 21 at 15:18 florpflorp 475 bronze badges 2
  • 1 You don't. A Dockerfile can never interact with a database or other containers. Consider docker building the image, docker pushing it to a repository, and then docker running it on a different machine with a different database container; it won't see any database updates that happened on the build system. – David Maze Commented Jan 21 at 16:23
  • 1 I don't think your database is running in the same container. How do you run your database? In a different container (probably with docker-compose)? – Koala Yeung Commented Jan 22 at 15:28
Add a comment  | 

3 Answers 3

Reset to default 1

It is simple. Your database do not run in this application container. Rather, it is probably running in a different container (i.e. hostname db in your environment).

When your image is building, it has no access to other running container(s).

So instead of using RUN to do things in build time, you should probably have script in your container to run the import when you first run the image against your environment, which provides proper access to the database.

This is a problem with the RUN directive, more specifically the command in it:

RUN wait-for-it -t 30 ${DB_HOST}:${DB_PORT} \
if [ -f /var/www/database/bsp.sql ]; then \
    mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; \
fi

What we can see is, that these compound commands do result in exit code 2.

This is a hint that it is a syntax error, because in the first line the wait-for-it command is not separated from the if that follows.

Insert a semicolon ";" and additionally set the sh(1) shell options to errexit (-e) and xtrace (-x) to have it more straight forward:

RUN set -ex; \
    wait-for-it -t 30 ${DB_HOST}:${DB_PORT}; \
    if [ -f /var/www/database/bsp.sql ]; then \
        mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} ${DB_DATABASE} < /var/www/database/bsp.sql; \
    fi

Additionally look into the build log for messages like

sh: syntax error near unexpected token `then'

or similar.


There are some other sloppy things in the Dockerfile, double check also the COPY lines, it looks like you are copying two times the same files. Before adding new functionality into the build, clean up first and commit the files to version control. Then it's easier to throw things around with Dockerfiles.

I've did it, thanks for your answers! This is the complete docker-compose.yml file. I've used /docker-entrypoint-initdb.d/ directory where I placed the database to be imported.

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: my-laravel-app
    container_name: my-laravel-app
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - ./.env:/var/www/.env
    environment:
      - APP_ENV=local
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    container_name: my-nginx
    ports:
      - "8000:80"
      - "${VITE_PORT:-5173}:${VITE_PORT:-5173}"
    volumes:
      - ./:/var/www
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
    depends_on:
      - app
    networks:
      - app-network        

  node:
    platform: linux/arm64/v8
    build:
      context: .
      dockerfile: Dockerfile.node
    image: my-laravel-node
    container_name: my-laravel-node
    ports:
      - "3000:3000"
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - /var/www/node_modules
    networks:
      - app-network

  db:
    platform: linux/x86_64
    image: mysql:8.0
    container_name: my-mysql
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
    volumes:
      - dbdata:/var/lib/mysql
      - ./data.sql:/docker-entrypoint-initdb.d/data-dump.sql  
    networks:
      - app-network
    ports:
      - "3306:3306"

networks:
  app-network:
    driver: bridge

volumes:
  dbdata:
    driver: local

本文标签: phpHow to import database inside dockerfileStack Overflow