在使用 terraform 的 Docker 容器中时,Laravel 无法连接到数据库

问题描述 投票:0回答:0

当我运行 (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"]
mysql laravel terraform contains
© www.soinside.com 2019 - 2024. All rights reserved.