在 docker compose 上执行 SQL 脚本
Posted
技术标签:
【中文标题】在 docker compose 上执行 SQL 脚本【英文标题】:Execute SQL script on docker compose 【发布时间】:2020-01-27 07:26:57 【问题描述】:我有一个项目,当 ./entrypoint.sh 或 docker-compose up 从项目的根目录运行并生成 swagger API 接口时运行,但调用返回入口响应没有数据。
如果我在没有 docker 的情况下在 localhost 上使用 mysql 运行,则效果很好。如何加载数据?
入口点.sh
#!/bin/bash
docker network create turingmysql
docker container run -p 3306:3306 --name mysqldb --network turingmysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=tshirtshop -d mysql:5.7
docker-compose build
docker-compose up
Docker 文件
FROM mysql:5.7
ADD ./database/tshirtshop.sql /docker-entrypoint-initdb.d
#### Stage 1: Build the application
FROM openjdk:8-jdk-alpine as build
# Set the current working directory inside the image
WORKDIR /app
# Copy maven executable to the image
COPY mvnw .
COPY .mvn .mvn
# Copy the pom.xml file
COPY pom.xml .
# Build all the dependencies in preparation to go offline.
# This is a separate step so the dependencies will be cached unless
# the pom.xml file has changed.
RUN ./mvnw dependency:go-offline -B
# Copy the project source
COPY src src
# Package the application
RUN ./mvnw package -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
#### Stage 2: A minimal docker image with command to run the app
FROM openjdk:8-jre-alpine
ARG DEPENDENCY=/app/target/dependency
# Copy project dependencies from the build stage
COPY --from=build $DEPENDENCY/BOOT-INF/lib /app/lib
COPY --from=build $DEPENDENCY/META-INF /app/META-INF
COPY --from=build $DEPENDENCY/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.turing.ecommerce.TuringApplication"]
docker-compose.yml
version: '3.7'
# Define services
services:
# App backend service
app-server:
# Configuration for building the docker image for the backend service
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080" # Forward the exposed port 8080 on the container to port 8080 on the host machine
restart: always
depends_on:
- mysqldb # This service depends on mysql. Start that first.
environment: # Pass environment variables to the service
SPRING_DATASOURCE_URL: jdbc:mysql://mysqldb:3306/tshirtshop?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
networks: # Networks to join (Services on the same network can communicate with each other using their name)
- turingmysql
# Database Service (Mysql)
mysqldb:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
environment:
MYSQL_DATABASE: tshirtshop
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: root
volumes:
- db-data:/var/lib/mysql
networks:
- turingmysql
# Volumes
volumes:
db-data:
# Networks to be created to facilitate communication between containers
networks:
turingmysql:
【问题讨论】:
那么,tshirtshop.sql
是否将任何值插入数据库?您的应用程序是否正确配置为查询数据库而不返回空结果?
是的,很多创建表和插入语句。
您是否在 API 中插入了日志语句以验证应该返回的内容?
如果我在没有 docker 的情况下运行,API 调用会返回数据。我已经部署在heroku 上,我在其中单独创建了数据库并进行了部署,它可以工作,但我需要对其进行 docker 化。
【参考方案1】:
感谢cricket_007 和Adii 的回复。他们把我引向了正确的方向。我想记录我的经验以及问题是如何解决的。码头化的新手,所以我是通过实践来学习的。对于任何刚接触 dockerization 并在 Spring Boot、MySQL 和 docker 中遇到相同问题的人,这肯定会有所帮助
首先,我的 entrypoint.sh 在下面发生了变化。 docker-compose down 用于重启。
#!/bin/bash
docker-compose down -v
docker-compose up --build
其次,我不得不使用现有的 mysql 映像而不是构建一个。
version: '3.7'
# Define services
services:
# App backend service
app-server:
# Configuration for building the docker image for the backend service
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080" # Forward the exposed port 8080 on the container to port 8080 on the host machine
restart: always
depends_on:
- mysql # This service depends on mysql. Start that first.
environment: # Pass environment variables to the service
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/tshirtshop?useSSL=false&allowPublicKeyRetrieval=true&useLegacyDatetimeCode=false&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: turing
SPRING_DATASOURCE_PASSWORD: pass
networks: # Networks to join (Services on the same network can communicate with each other using their name)
- turingmysql
# Database Service (Mysql)
mysql:
image: mysql/mysql-server
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: tshirtshop
MYSQL_USER: turing
MYSQL_PASSWORD: pass
volumes:
- db-data:/var/lib/mysql
- ./database:/docker-entrypoint-initdb.d
tty: true
networks: # Networks to join (Services on the same network can communicate with each other using their name)
- turingmysql
# Volumes
volumes:
db-data:
# Networks to be created to facilitate communication between containers
networks:
turingmysql:
driver: bridge
需要指定网络是一个网桥。我的 sql 文件是从相对于 docker-compose.yml 的文件夹安装的。还必须将 allowPublicKeyRetrieval=true 添加到我的 jdbc url。创建了一个用户来访问数据库 tshirtshop。
这里是 Dockerfile。
#### Stage 1: Build the application
FROM openjdk:8-jdk-alpine as build
# Set the current working directory inside the image
WORKDIR /app
# Copy maven executable to the image
COPY mvnw .
COPY .mvn .mvn
# Copy the pom.xml file
COPY pom.xml .
# Build all the dependencies in preparation to go offline.
# This is a separate step so the dependencies will be cached unless
# the pom.xml file has changed.
RUN ./mvnw dependency:go-offline -B
# Copy the project source
COPY src src
# Package the application
RUN ./mvnw package -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
#### Stage 2: A minimal docker image with command to run the app
FROM openjdk:8-jre-alpine
ARG DEPENDENCY=/app/target/dependency
# Copy project dependencies from the build stage
COPY --from=build $DEPENDENCY/BOOT-INF/lib /app/lib
COPY --from=build $DEPENDENCY/META-INF /app/META-INF
COPY --from=build $DEPENDENCY/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.turing.ecommerce.TuringApplication"]
运行,从项目的根目录 ./entrypoint.sh 在 mac 上,其余的都是历史。
【讨论】:
【参考方案2】:你有两个 Dockerfile 吗?看起来您构建了自己的 MySQL 容器?
否则,这些不应该是您的 Java 多阶段构建的一部分
FROM mysql:5.7
ADD ./database/tshirtshop.sql /docker-entrypoint-initdb.d
假设您确实为 mysql 构建了一个单独的映像,在 Docker-Compose 中,您没有使用它,因为您仍然指的是image: mysql:5.7
与其自己构建,不如将 SQL 脚本挂载到其中
例如
mysqldb:
image: mysql:5.7
...
volumes:
- db-data:/var/lib/mysql
- ./database/tshirtshop.sql:/docker-entrypoint-initdb.d/0_init.sql
然后,暂时忘记 Java 服务并使用 MySQL 工作台或 mysql CLI 来验证数据是否确实存在。完成后,启动 API
【讨论】:
我只有一个 dockerfile。我已经删除了这两行并尝试安装,没有喘息的机会。 如果你做docker-compose logs mysqldb
,你看到它运行脚本了吗?
docker-compose rm -sf mysqldb
,然后重新启动
另外,您应该从脚本中删除 docker container run
,因为您是在 docker-compose up 命令中启动 mysql【参考方案3】:
如果您已经将sql
scipt 复制到 docker build,那么您不需要在 docker-compose 中再次映射它,如果您有 docker-compose,那么您不会使用 bash 脚本单个命令 docker-compose up --build
来执行工作。
所以根据你的 Dockerfile 修改你的 docker-compose。
Dockerfile
FROM mysql
ADD init.sql /docker-entrypoint-initdb.d
码头工人撰写
version: '3.7'
services:
# App backend service
app-server:
# Configuration for building the docker image for the backend service
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080" # Forward the exposed port 8080 on the container to port 8080 on the host machine
restart: always
depends_on:
- mysqldb # This service depends on mysql. Start that first.
environment: # Pass environment variables to the service
SPRING_DATASOURCE_URL: jdbc:mysql://mysqldb:3306/tshirtshop?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
networks: # Networks to join (Services on the same network can communicate with each other using container name)
- uringmysql
# Database Service (Mysql)
mysql:
build: .
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: appdata
MYSQL_USER: test
MYSQL_PASSWORD: root123
volumes:
- db-data:/var/lib/mysql
tty: true
# Volumes
volumes:
db-data:
# Networks to be created to facilitate communication between containers
networks:
turingmysql:
现在运行
docker-compose up --build
这将构建和构建容器,您不需要映射主机初始化脚本,因为它已经在 Docker 映像中。
目录结构如下所示
现在您的应用程序将能够使用jdbc:mysql://mysqldb:3306/tshirtshop?
这个端点访问数据库,因为两者都在同一个网络中,并且可以使用名称相互引用。
【讨论】:
以上是关于在 docker compose 上执行 SQL 脚本的主要内容,如果未能解决你的问题,请参考以下文章
docker-compose mysql init sql 未执行
Docker-compose 与 H2 docker 数据库的 setup.sql 文件