Docker for WindowsでLaravel+OCI8の複数プロジェクト開発環境を作ってみた

普段レガシーなシステムをごにょごにょお世話しているレガシーなプログラマーです。
中高年でもイマドキ風の開発をやってみたい！
でも仕事で使うDBはうちはORACLEが多い…
ということで、LaravelでOCIを使える環境を作ってみました。

普通に開発環境を作るならLaraDockが色々揃っていますし、他に良い記事が沢山あると思います
[Laravelの開発環境をDockerを使って構築する](https://qiita.com/ucan-lab/items/17c806973e69792ada99)

# Docker Desktop on Windowsのインストール

まずはDockerの準備です。動作条件を確認。

- Windows10 pro 64bit
- メモリは4GB以上
- Hyper-Vが使えること

ほぼこちらの説明通りで設定できました。ありがとうございます！
https://qiita.com/ksh-fthr/items/6b1242c010fac7395a45

### ダウンロード＆インストール

公式サイトからインストーラーをダウンロードします。
この時、Docker Hubのアカウントも作成することになります。サクッと登録しましょう。

https://docs.docker.com/docker-for-windows/install/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317794/2ca19281-ba01-7fbf-4b7c-c7917e87bf83.png)

### docker-composeのインストール

Docker for Macは個別に入れなくてもよかったのですがWindows版は手動で入れないといけません。
1.Powershell を管理者権限で起動する。
2.以下のコマンドを実行する。DockerのUpdateのたびに実行する必要があるのがメンドイ。

```
Invoke-WebRequest "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Windows-x86_64.exe" -UseBasicParsing -OutFile $Env:ProgramFiles\docker\docker-compose.exe
```

### Shared Drivesの設定
チェックを入れて「Apply」をクリック。
Dockerを再起動してちゃんと設定できているか確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317794/5ebdad14-007c-e4ff-3b90-96de4923a40d.png)

#docker-compose.yml作成
こんな構成で作成しました。
[lara73oci]
 ├ docker-compose.yml
 ├ [nginx]
 │  ├ [sites]　<=ここにサイトの設定を入れる
 │  ├ Dockerfile
 │  └ nginx.conf
 ├ [php7.3]
 │  ├ Dockerfile
 │  ├ instantclient-basic-linux.x64-12.2.0.1.0.zip　<=Oracleからダウンロードしてきます
 │  ├ instantclient-sdk-linux.x64-12.2.0.1.0.zip　<=Oracleからダウンロードしてきます
 │  ├ php.ini
 │  └ tnsnames.ora
 ├ [src]　　<=ここにプログラム
 └ [logs]　<=nginxのログ


```yml:docker-compose.yml
version: '3'
services:
  nginx:
    build:
      context: ./nginx
    volumes:
      - ./src:/var/www:cached
      - ./logs/nginx/:/var/log/nginx
      - ./nginx/sites/:/etc/nginx/sites-available
    ports:
      - "80:80"
    depends_on:
      - php-fpm
  php-fpm:
    build:
      context: ./php7.3
      dockerfile: Dockerfile
    volumes:
      - ./php7.3/php.ini:/usr/local/etc/php/php.ini
      - ./php7.3/tnsnames.ora:/usr/local/instantclient/tnsnames.ora
      - ./src:/var/www:cached
    expose:
      - "9000"
```
複数プロジェクトを動かしたかったのでsites-availableを使っています。

#nginx

```dockerfile:nginx/Dockerfile
FROM nginx:alpine

COPY nginx.conf /etc/nginx/

RUN apk update \
    && apk upgrade \
    && apk add --no-cache bash

RUN set -x ; \
    addgroup -g 82 -S www-data ; \
    adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1

RUN rm /etc/nginx/conf.d/default.conf

CMD ["nginx"]

EXPOSE 80 443
```

```nginx:nginx/nginx.conf
user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;

events {
  worker_connections  2048;
  multi_accept on;
  use epoll;
}

http {
  server_tokens off;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 15;
  types_hash_max_size 2048;
  client_max_body_size 20M;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  access_log /dev/stdout;
  error_log /dev/stderr;
  gzip on;
  gzip_disable "msie6";

  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-available/*.conf;
  open_file_cache off; # Disabled for issue 619
  charset UTF-8;
}
```

サイトの設定です。

```nginx:nginx/sites/default.conf
server {

  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  server_name localhost;
  root /var/www/public;
  index index.php index.html index.htm;

  location / {
     try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    try_files $uri /index.php =404;
    fastcgi_pass php-fpm:9000;
    fastcgi_index index.php;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #fixes timeouts
    fastcgi_read_timeout 600;
    include fastcgi_params;
  }

  location ~ /\.ht {
    deny all;
  }

  location /.well-known/acme-challenge/ {
    root /var/www/letsencrypt/;
    log_not_found off;
  }
}
```

### 複数プロジェクトで使用する場合

nginx/sitesのproject1.confをコピーして使用してください

（例）*project_hoge.conf*

ファイル内のproject1、project1.local を自分のプロジェクトに合わせて変更してください
もちろんDocument rootも！

#PHP+OCI8

### Oracle instant clientの入手

 [Instant Client for Linux x86-64](https://www.oracle.com/technetwork/jp/topics/linuxx86-64soft-085244-ja.html)からinstantclient-basicとinstantclient-sdkを**zip形式で**ダウンロードして
php7.3のDockerFileと同じディレクトリに置いてください
バージョンは12.2と12.1で確認しました
（例）
./php7.3/instantclient-sdk-linux.x64-12.2.0.1.0.zip
./php7.3/instantclient-basic-linux.x64-12.2.0.1.0.zip

### php7.3/DockerFileの編集

入手したファイル名に合わせて13~25行目を変更してください

### php7.3/tnsnames.oraの編集

ご自分の環境に合わせて記述してください

```dockerfile:php7.3/Dockerfile
FROM php:7.3-fpm

RUN apt-get update && \
  apt-get install -y git \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev && \
  docker-php-ext-install gd pdo_mysql mysqli mbstring bcmath

ENV LD_LIBRARY_PATH /usr/local/instantclient/
ENV TNS_ADMIN /usr/local/instantclient/

COPY instantclient-basic-linux.x64-12.2.0.1.0.zip /tmp
COPY instantclient-sdk-linux.x64-12.2.0.1.0.zip /tmp

RUN apt-get update && \
    apt-get install -y zip unzip libaio1 wget && \
    unzip /tmp/instantclient-basic-linux.x64-12.2.0.1.0.zip -d /usr/local/ && \
    unzip /tmp/instantclient-sdk-linux.x64-12.2.0.1.0.zip -d /usr/local/ && \
    ln -s /usr/local/instantclient_12_2 /usr/local/instantclient && \
    ln -s /usr/local/instantclient/libclntsh.so.12.1 /usr/local/instantclient/libclntsh.so && \
    export LD_LIBRARY_PATH=/usr/local/instantclient && \
    docker-php-ext-configure oci8 --with-oci8=instantclient,/usr/local/instantclient && \
	docker-php-ext-install oci8 && \ 
	docker-php-ext-configure pdo_oci --with-pdo-oci=instantclient,/usr/local/instantclient,12.2 && \
	docker-php-ext-install pdo_oci && \
    rm -rf /usr/local/*.zip

RUN apt-get install -y \
    curl \
    gnupg
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs
RUN npm install npm@latest -g

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
```
Laravel用にnpmやcomposerも入るようにしています
Oracle instant client導入～OCI8のインストール部分は
LaraDockのworkspaceとphp-fpmのDockerfileに同様の設定をいれると動くと思います。
LaraDockでやりたい方はお試しあれ！


### /etc/hostsを変更

Windows10の場合はC:\Windows\System32\drivers\etc\hosts
**管理者モードで**メモ帳を起動して設定したホスト名を追記します。
これで http://project1.local/ でアクセスできるようになります。

```
127.0.0.1	project1.local
::1 project1.local
127.0.0.1	project2.local
::1 project2.local
```

# 起動
```
docker-compose up -d
```

#LaravelのインストールとOCI8設定

１．php-fpmに入ります

```dos
docker-compose exec php-fpm bash
```
２．Laravelのインストール

```bash
$ cd /var/www 　<=設定したドキュメントルートに合うようにしてください
$ composer create-project --prefer-dist laravel/laravel project1 "5.8.*" <=5.8の場合
$ composer create-project --prefer-dist laravel/laravel project1　<=最新版
```

３．yajra/laravel-oci8のインストール
https://github.com/yajra/laravel-oci8
ドキュメント通りにLaravelのバージョンにあわせてcomposerでインストールします
Laravelのディレクトリに移動して

```bash
$ composer require yajra/laravel-oci8:"5.8.*"  <=Laravel5.8
$ composer require yajra/laravel-oci8:"^6.0"	 <=Laravel6~
```

４．Laravelのconfig/app.phpのproviders内に追加します

```php:config/app.php
'providers' => [
    // ...
    Yajra\Oci8\Oci8ServiceProvider::class,
],
```

５．config/oracle.phpの作成

```bash
php artisan vendor:publish --tag=oracle
```

６．.env内のORACLEの設定

```php:.env
DB_CONNECTION=oracle
DB_HOST=xxx.xxx.xxx.xxx
DB_PORT=1521
DB_DATABASE=oracleのSID
DB_USERNAME=xxx
DB_PASSWORD=xxx
```

以上でMySQLと同じようにDBの操作ができました。

#リポジトリ
作成したOracle instant client本体なしの雛形リポジトリを置いておきます。
Docker初心者なのでここはこうしたほうがいいよと教えていただけると嬉しいです！
https://github.com/anissia0828/nginx_php73_oci

#参考にさせていただきました
[laravelでoracleと接続する方法](https://blog.nobug-nolife.com/entry/2018/10/29/011840)
[【Laravel】Laradockで複数プロジェクトを動かす手順](https://pensuke.work/posts/laradock-multiproject/)