当我运行 (Laravel 8) php artisan php artisan passport:install 时,我似乎无法连接到数据库并出现错误:
2023-04-14 18:19:46 wait-for-it: waiting 20 seconds for vcard-mysql-container:3306
2023-04-14 18:20:06 wait-for-it: timeout occurred after waiting 20 seconds for vcard-mysql-container:3306
2023-04-14 18:20:07 Encryption keys generated successfully.
2023-04-14 18:20:10
2023-04-14 18:20:10 Illuminate\Database\QueryException
2023-04-14 18:20:10
2023-04-14 18:20:10 SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for vcard-mysql-container failed: Name or service not known (SQL: insert into `oauth_clients` (`user_id`, `name`, `secret`, `provider`, `redirect`, `personal_access_client`, `password_client`, `revoked`, `updated_at`, `created_at`) values (?, Laravel Personal Access Client, Ki1qzPH9Azw3yJS7xZIMlw9mPL3cizHZcfaGIxUZ, ?, http://localhost, 1, 0, 0, 2023-04-14 17:20:07, 2023-04-14 17:20:07))
2023-04-14 18:20:10
2023-04-14 18:20:10 at vendor/laravel/framework/src/Illuminate/Database/Connection.php:703
2023-04-14 18:20:10 699▕ // If an exception occurs when attempting to run a query, we'll format the error
2023-04-14 18:20:10 700▕ // message to include the bindings with SQL, which will make this exception a
2023-04-14 18:20:10 701▕ // lot more helpful to the developer instead of just the database's errors.
2023-04-14 18:20:10 702▕ catch (Exception $e) {
2023-04-14 18:20:10 ➜ 703▕ throw new QueryException(
2023-04-14 18:20:10 704▕ $query, $this->prepareBindings($bindings), $e
2023-04-14 18:20:10 705▕ );
2023-04-14 18:20:10 706▕ }
2023-04-14 18:20:10 707▕ }
2023-04-14 18:20:10
2023-04-14 18:20:10 +46 vendor frames
2023-04-14 18:20:10 47 artisan:37
2023-04-14 18:20:10 Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
我在 docker-compose 上有相同的变量并且一切正常,但是当我使用 terraform 时我得到了之前的错误(我认为当 api 容器尝试运行命令时 mysql 服务还没有准备好但是我在脚本中添加了 200s等待并得到相同的)。
我用
docker-compose build
构建图像,然后我做 terraform terraform apply
我的 docker-compose(只是为了检查我在做什么):
version: '3'
services:
vcard-mysql: #Mysql container (Server)
build:
context: ./mysql
dockerfile: Dockerfile
image: vcard-mysql-image
restart: always
container_name: vcard-mysql-container
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
interval: 15s
retries: 100
networks:
- vcard-network
vcard-api: #API container (Server)
build:
context: ./api
dockerfile: Dockerfile
# args:
# - APP_DEBUG=${API_APP_DEBUG}
# - DB_HOST=${API_DB_HOST}
# - DB_DATABASE=${MYSQL_DATABASE}
# - DB_USERNAME=${MYSQL_USER}
# - DB_PASSWORD=${MYSQL_PASSWORD}
environment:
APP_DEBUG: ${API_APP_DEBUG}
DB_HOST: ${API_DB_HOST}
DB_DATABASE: ${MYSQL_DATABASE}
DB_USERNAME: ${MYSQL_USER}
DB_PASSWORD: ${MYSQL_PASSWORD}
image: vcard-api-image
restart: always
container_name: vcard-api-container
ports:
- "80:80"
depends_on:
vcard-mysql:
condition: service_healthy
networks:
- vcard-network
vcard-sockets: #Websockets container (Server)
build:
context: ./sockets
dockerfile: Dockerfile
environment:
NODE_PORT: ${NODE_PORT}
image: vcard-sockets-image
restart: always
container_name: vcard-sockets-container
ports:
- "8085:${NODE_PORT}"
networks:
- vcard-network
vcard-vue: #Vue container (Client)
build:
context: ./client
dockerfile: Dockerfile
environment:
VUE_APP_API_DOMAIN: ${VUE_APP_API_DOMAIN}
VUE_APP_WS_CONNECTION: ${VUE_APP_WS_CONNECTION}
NODE_ENV: ${NODE_ENV}
image: vcard-vue-image
restart: always
container_name: vcard-vue-container
ports:
- "8080:80"
depends_on:
- vcard-api
- vcard-sockets
networks:
- vcard-network
networks:
vcard-network:
driver: bridge
我的环境文件:
VUE_APP_API_DOMAIN=http://localhost
VUE_APP_WS_CONNECTION=http://localhost:8085
NODE_ENV=production
NODE_PORT=80
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=projeto
MYSQL_USER=vcard
MYSQL_PASSWORD="root"
API_APP_DEBUG=false
API_DB_HOST=vcard-mysql-container
我的地形文件:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {}
resource "docker_container" "vcard_mysql" {
name = "vcard-mysql-container"
image = "vcard-mysql-image"
env = [
"MYSQL_ROOT_PASSWORD=root",
"MYSQL_DATABASE=projeto",
"MYSQL_USER=vcard",
"MYSQL_PASSWORD=root",
]
healthcheck {
test = ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval = "15s"
retries = 100
}
ports {
internal = 3306
external = 3306
}
}
resource "docker_container" "vcard_api" {
name = "vcard-api-container"
image = "vcard-api-image"
env = [
"APP_DEBUG=true",
"DB_HOST=vcard-mysql-container", //Doesn't work
"DB_DATABASE=projeto",
"DB_USERNAME=vcard",
"DB_PASSWORD=root",
]
ports {
internal = 80
external = 80
}
depends_on = [
docker_container.vcard_mysql,
]
}
resource "docker_container" "vcard_sockets" {
name = "vcard-sockets-container"
image = "vcard-sockets-image"
env = [
"NODE_PORT=${var.node_port}",
]
ports {
internal = var.node_port
external = 8085
}
}
resource "docker_container" "vcard_vue" {
name = "vcard-vue-container"
image = "vcard-vue-image"
env = [
"VUE_APP_API_DOMAIN=http://localhost",
"VUE_APP_WS_CONNECTION=http://localhost:8085",
"NODE_ENV=${var.node_env}",
]
ports {
internal = 80
external = 8080
}
depends_on = [
docker_container.vcard_api, docker_container.vcard_sockets
]
}
我的地形变量:
variable "mysql_root_password" {
description = "MySQL root password"
type = string
default = "root"
}
variable "mysql_database" {
description = "MySQL database name"
type = string
default = "projeto"
}
variable "mysql_user" {
description = "MySQL user name"
type = string
default = "vcard"
}
variable "mysql_password" {
description = "MySQL user password"
type = string
default = "root"
}
variable "api_app_debug" {
description = "API app debug"
type = bool
default = false
}
variable "node_env" {
description = "Vue app environment"
type = string
default = "production"
}
variable "node_port" {
description = "value for NODE_PORT"
type = number
default = 80
}
Finnaly 我的 API DockerFile:
# Set the base image to the official PHP 8.1.10 image with Apache
FROM php:8.1.10-apache
# Install system dependencies
RUN apt-get update && \
apt-get install -y \
libzip-dev \
zip \
unzip \
libonig-dev \
libxml2-dev \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
curl
# Set the locale
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen
# Clear cache
RUN apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl bcmath gd opcache
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Enable Apache modules
RUN a2enmod rewrite headers
# Create a new directory for the application
RUN mkdir -p /var/www/html
# Set the working directory
WORKDIR /var/www/html
# Copy the application files to the container
COPY . /var/www/html
RUN mv .env.example .env
# Set file permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
# Install application dependencies
RUN composer install
RUN rm -rf /var/www/html/public/storage
RUN ln -s /var/www/html/storage/app/public /var/www/html/public/storage
# Copy virtual host configuration
COPY ./laravel.conf /etc/apache2/sites-available/
# Enable virtual host
RUN a2dissite 000-default.conf
RUN a2ensite laravel.conf
RUN a2enmod rewrite
RUN service apache2 restart
# Add wait-for-it script
ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /usr/local/bin/wait-for-it
RUN chmod +x /usr/local/bin/wait-for-it
# Start Apache and wait for MySQL to be ready
CMD ["bash", "-c", "wait-for-it ${DB_HOST}:3306 -t 20 -- php artisan passport:install && php artisan key:generate && apache2-foreground"]