Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?
@k-tabuchi

dockerでsymfony & mysql & phpmyAdminのローカル開発環境を作る。①

概要

dockerでsymfonyの構築ができたので、動いた時点のファイルをメモしています。
このページは参考ページをもとにしているため、合わせて読むとわかりやすいです。

環境

M1チップMac
BigSur

2021/5/11時点で動作。

前提

Docker-syncがインストールされている。
まだの場合、一番下の参考ページにコマンドがあるのでコピペして実行してください。

Dockerは知っている。
コンテナ、イメージ、ボリュームは知っている。
apacheのconfや.htaccessはどういうものかわかる。
MAMPや簡易サーバでなら構築できる。
Linuxの基本はわかる。

参考ページと同じディレクトリ構成を作る。

任意の空のフォルダに移動して、下記のコマンド。

touch create_docker_dir.sh 

できたファイルに以下をコピペ。
docker-sync.yaml だと この後の工程でエラーになったので拡張子に注意(aが余分)。
docker-comopseは逆にyamlなので紛らわしいです。
また、DockerfileはDockerFileとかくとエラーになります。
ハマるポイントが多いので手でタイプするのはやめた方がいいです。

create_docker_dir.sh
#!/bin/bash

mkdir app
mkdir -p docker/apache docker/php

touch docker/apache/my_app.conf
touch docker/php/php.ini
touch docker/Dockerfile
touch .env docker-compose.yaml docker-sync.yml

シェルを実行。

sh create_docker_dir.sh

DockerFileにコピペする。

DockerFileの内容
参考ページのままだとドライバがないというエラーが起きた。
MySQLを使う場合は以下を追記。
なぜか書かないとsqlLigteのドライバしかない。
他は丸写しだったと思う。

RUN docker-php-ext-install pdo_mysql mysqli

./docker/DockerFile

FROM php:7.4-apache

RUN cd /etc/apache2/mods-enabled \
    && ln -s ../mods-available/rewrite.load

RUN a2dissite 000-default

WORKDIR /var/www/html

RUN apt-get update && apt-get install -y git zip unzip
RUN apt-get install -y wget libjpeg-dev libfreetype6-dev
RUN apt-get install -y  libmagick++-dev \
libmagickwand-dev \
libpq-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libwebp-dev \
libxpm-dev

RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN docker-php-ext-install pdo_mysql mysqli

RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && mv /usr/bin/composer.phar /usr/bin/composer

docker-composeにコピペする

./docker-comose.yml
version: '3'

volumes:
  mysql-database:
    driver: local
  my_app_symfony:
    external: true

services:
  app:
    container_name: my_app
    build: ./docker
    ports:
      - 8901:80
    volumes:
      - my_app_symfony:/var/www/html
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
      - ./docker/apache/my_app.conf:/etc/apache2/sites-enabled/my_app.conf
    depends_on:
      - mysql
    environment:
      DATABASE_URL: "mysql://root:root@mysql/app_db"
      DATABASE_SERVER_VERSION: 10

  mysql:
    image: mysql:5.7
    container_name: my_app_app_mysql
    environment:
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - 13306:3306
    platform: linux/x86_64
    volumes:
      - mysql-database:/var/lib/mysql

  phpmyadmin:
      image: phpmyadmin/phpmyadmin
      environment:
          - PMA_ARBITRARY=1
          - PMA_HOST=mysql
          - PMA_USER=root
          - PMA_PASSWORD=$DB_ROOT_PASSWORD
      links:
          - mysql
      ports:
          - 8902:80
      volumes:
          - /sessions

docker-syncにコピペする

my_app_symfonyの部分は、プロジェクトごとに別の名前をつけないと同じソースコードを参照してしまうので注意。
変更した場合、docker-composeも同じ名前に揃える。

./docker-sync.yml
version: '2'
syncs:
  my_app_symfony:
    src: './app'
    sync_host_ip: '127.0.0.1'
    sync_host_port: '5000'
    sync_strategy: 'native_osx'
    sync_excludes: ['.git', '.gitignore', 'node_modules']

.envにコピペする

./.env

DB_ROOT_PASSWORD=root
DB_NAME=app_db

my_app.confにコピペする

参考ページからDirectoryタグの中を追記しました。
公開ディレクトリにAllowOverride Allの記述がないとSymfonyのルーティングが弾かれます。
対象フォルダの.htaccessを有効化する記述みたいです。

./docker/apache/my_app.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/my_app/public
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<Directory /var/www/html/my_app/public>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
</Directory>

php.iniにコピペする

./docker/php/php.ini

memory_limit = 2048M
date.timezone = "Asia/Tokyo"
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

docker-syncを起動する

コンテナから切り離して永続させるフォルダをマウントする。

docker-sync start

success Sync container started
success Starting Docker-Sync in the background
が出て、
.docker-syncディレクトリが新たに出現していたら成功。

コンテナを立ち上げる

-d をつけるとバックで処理してくれる。
--build をつけるとDockerFileをコンパイルしてimageを生成しなおす(多分)。
なのでDockerFileを編集したら--buildオプションをつける。
止めるときはdocker-compose down

docker-compose up -d --build

この時点でこうなっている。
appフォルダの中はまだ空。

スクリーンショット 2021-05-11 18.15.14.png

Symfonyをインストール

コンテナの中に入る
symfony/skeletonだとweb関連のファイルがインストールされない。

docker-compose exec app /bin/bash
composer create-project symfony/website-skeleton my_app

今、こうなっている。
/app配下がsymfonyプロジェクトになっているようです。

スクリーンショット 2021-05-11 18.53.00.png

アクセスする。

ここまで合っていれば、以下のページが表示されるはず。

symfony
http://localhost:8901/

phpMyAdmin
http://localhost:8902/

Symfonyからルーティングできるようにする。

このままの状態では、welcomeページしか表示できません。
他のページにアクセスすると全て404 not found エラーでapacheに弾かれます。
そこでプロジェクトフォルダのpublicフォルダ内に.htaccessを置いて許可設定を記述します。

cd ./app/my_app/public
touch .htaccess

できたファイルに以下をコピペする。
何か専用のコマンドを打つとできたような気がしますけど、どこで見たか忘れました。
自分で貼り付けても動いているので問題ないと思います。

./app/my_app/public/.htaccess

# Use the front controller as index file. It serves as a fallback solution when
# every other rewrite/redirect fails (e.g. in an aliased environment without
# mod_rewrite). Additionally, this reduces the matching process for the
# start page (path "/") because otherwise Apache will apply the rewriting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
DirectoryIndex index.php

# By default, Apache does not evaluate symbolic links if you did not enable this
# feature in your server configuration. Uncomment the following line if you
# install assets as symlinks or if you experience problems related to symlinks
# when compiling LESS/Sass/CoffeScript assets.
# Options +FollowSymlinks

# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve
# to the front controller "/index.php" but be rewritten to "/index.php/index".
<IfModule mod_negotiation.c>
    Options -MultiViews
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Determine the RewriteBase automatically and set it as environment variable.
    # If you are using Apache aliases to do mass virtual hosting or installed the
    # project in a subdirectory, the base path will be prepended to allow proper
    # resolution of the index.php file and to redirect to the correct URI. It will
    # work in environments without path prefix as well, providing a safe, one-size
    # fits all solution. But as you do not need it in this case, you can comment
    # the following 2 lines to eliminate the overhead.
    RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
    RewriteRule .* - [E=BASE:%1]

    # Sets the HTTP_AUTHORIZATION header removed by Apache
    RewriteCond %{HTTP:Authorization} .+
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]

    # Redirect to URI without front controller to prevent duplicate content
    # (with and without `/index.php`). Only do this redirect on the initial
    # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
    # endless redirect loop (request -> rewrite to front controller ->
    # redirect -> request -> ...).
    # So in case you get a "too many redirects" error or you always get redirected
    # to the start page because your Apache does not expose the REDIRECT_STATUS
    # environment variable, you have 2 choices:
    # - disable this feature by commenting the following 2 lines or
    # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
    #   following RewriteCond (best solution)
    RewriteCond %{ENV:REDIRECT_STATUS} =""
    RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

    # If the requested filename exists, simply serve it.
    # We only want to let Apache serve files and not directories.
    # Rewrite all other queries to the front controller.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        # When mod_rewrite is not available, we instruct a temporary redirect of
        # the start page to the front controller explicitly so that the website
        # and the generated links can still be used.
        RedirectMatch 307 ^/$ /index.php/
        # RedirectTemp cannot be used instead
    </IfModule>
</IfModule>

トップページ以外アクセスできるか試す。

テストコントローラを作る。symfonyはアノテーションでルーティングできるので同時にルートが生成されている。

cd ./my_app/
php bin/console make:controller HelloController

ここで、composerのphpバージョンが古いというようなエラーが出ました。
以下のコマンドを打ってからもう一度make:controllerしたら動きました。

composer update

symfony側からルーティングできているか確認。

php bin/console debug:route

apacheにブロックされないことを確認する。
http://localhost:8901/hello

続き

この後、symfonyでエンティティ作ってマイグレーションしたらエラーでつまづいたので、
その対処法を以下に書きました。

参考

主に以下のページをもとに、自分の環境で動かなかったところを編集しました。
他にも色々なページをググりまくりましたが、どれをどこでみたか覚えていません。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?