GMOアドマーケティングのy.yです。
今回は 2019/11/14 に一般提供版(GA)となった
GCPのCloud RunとCloud SQLでphpMyAdminを構築したいと思います。
Cloud Run は、ステートレス コンテナを自動的にスケールするマネージド型のコンピューティング プラットフォームです。Cloud Run はサーバーレスです。
元となるDockerfileはdockerhubのものを使用します。
※Cloud SQLのインスタンスは事前に作成しているものとします。
Cloud RunではDockerfile、apache設定、docker-entrypointに修正する必要があったので変更点を記載します。
変更点1:Dockerファイルを変更します
変更前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
FROM php:7.4-apache # Install dependencies RUN set -ex; \ \ savedAptMark="$(apt-mark showmanual)"; \ \ apt-get update; \ apt-get install -y --no-install-recommends \ libbz2-dev \ libfreetype6-dev \ libjpeg-dev \ libpng-dev \ libwebp-dev \ libxpm-dev \ libzip-dev \ ; \ \ docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm; \ docker-php-ext-install -j "$(nproc)" \ bz2 \ gd \ mysqli \ opcache \ zip \ ; \ \ apt-mark auto '.*' > /dev/null; \ apt-mark manual $savedAptMark; \ ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \ | awk '/=>/ { print $3 }' \ | sort -u \ | xargs -r dpkg-query -S \ | cut -d: -f1 \ | sort -u \ | xargs -rt apt-mark manual; \ \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ rm -rf /var/lib/apt/lists/* # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=2'; \ echo 'opcache.fast_shutdown=1'; \ } > $PHP_INI_DIR/conf.d/opcache-recommended.ini; \ \ { \ echo 'session.cookie_httponly = 1'; \ echo 'session.use_strict_mode = 1'; \ } > $PHP_INI_DIR/conf.d/session-strict.ini; \ \ { \ echo 'allow_url_fopen = Off'; \ echo 'max_execution_time = 600'; \ echo 'memory_limit = 512M'; \ } > $PHP_INI_DIR/conf.d/phpmyadmin-misc.ini # Calculate download URL ENV VERSION 5.0.1 ENV URL https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL version=$VERSION # Download tarball, verify it using gpg and extract RUN set -ex; \ fetchDeps=" \ gnupg \ dirmngr \ "; \ apt-get update; \ apt-get install -y --no-install-recommends $fetchDeps; \ \ export GNUPGHOME="$(mktemp -d)"; \ export GPGKEY="3D06A59ECE730EB71B511C17CE752F178259BD92"; \ curl --output phpMyAdmin.tar.xz --location $URL; \ curl --output phpMyAdmin.tar.xz.asc --location $URL.asc; \ gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver ipv4.pool.sks-keyservers.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver keys.gnupg.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY"; \ gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ tar -xf phpMyAdmin.tar.xz -C /usr/src; \ gpgconf --kill all; \ rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ mv /usr/src/phpMyAdmin-$VERSION-all-languages /usr/src/phpmyadmin; \ rm -rf /usr/src/phpmyadmin/setup/ /usr/src/phpmyadmin/examples/ /usr/src/phpmyadmin/test/ /usr/src/phpmyadmin/po/ /usr/src/phpmyadmin/composer.json /usr/src/phpmyadmin/RELEASE-DATE-$VERSION; \ sed -i "s@define('CONFIG_DIR'.*@define('CONFIG_DIR', '/etc/phpmyadmin/');@" /usr/src/phpmyadmin/libraries/vendor_config.php; \ # Add directory for sessions to allow session persistence mkdir /sessions; \ mkdir -p /var/nginx/client_body_temp; \ \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps; \ rm -rf /var/lib/apt/lists/* # Copy configuration COPY config.inc.php /etc/phpmyadmin/config.inc.php # Copy main script COPY docker-entrypoint.sh /docker-entrypoint.sh ENTRYPOINT [ "/docker-entrypoint.sh" ] CMD ["apache2-foreground"] |
変更後
3〜9行目追加(apacheの設定ファイル更新)
113行目追加(portのexport)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
FROM php:7.4-apache COPY ./sites-available-000-default.conf /etc/apache2/sites-available/000-default.conf COPY ./ports.conf /etc/apache2/ports.conf RUN echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf RUN a2enconf fqdn COPY ./config.secret.inc.php /etc/phpmyadmin/config.secret.inc.php # Install dependencies RUN set -ex; \ \ savedAptMark="$(apt-mark showmanual)"; \ \ apt-get update; \ apt-get install -y --no-install-recommends \ libbz2-dev \ libfreetype6-dev \ libjpeg-dev \ libpng-dev \ libwebp-dev \ libxpm-dev \ libzip-dev \ ; \ \ docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm; \ docker-php-ext-install -j "$(nproc)" \ bz2 \ gd \ mysqli \ opcache \ zip \ ; \ \ apt-mark auto '.*' > /dev/null; \ apt-mark manual $savedAptMark; \ ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \ | awk '/=>/ { print $3 }' \ | sort -u \ | xargs -r dpkg-query -S \ | cut -d: -f1 \ | sort -u \ | xargs -rt apt-mark manual; \ \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ rm -rf /var/lib/apt/lists/* # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=2'; \ echo 'opcache.fast_shutdown=1'; \ } > $PHP_INI_DIR/conf.d/opcache-recommended.ini; \ \ { \ echo 'session.cookie_httponly = 1'; \ echo 'session.use_strict_mode = 1'; \ } > $PHP_INI_DIR/conf.d/session-strict.ini; \ \ { \ echo 'allow_url_fopen = Off'; \ echo 'max_execution_time = 600'; \ echo 'memory_limit = 512M'; \ } > $PHP_INI_DIR/conf.d/phpmyadmin-misc.ini # Calculate download URL ENV VERSION 5.0.1 ENV URL https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL version=$VERSION # Download tarball, verify it using gpg and extract RUN set -ex; \ fetchDeps=" \ gnupg \ dirmngr \ "; \ apt-get update; \ apt-get install -y --no-install-recommends $fetchDeps; \ \ export GNUPGHOME="$(mktemp -d)"; \ export GPGKEY="3D06A59ECE730EB71B511C17CE752F178259BD92"; \ curl --output phpMyAdmin.tar.xz --location $URL; \ curl --output phpMyAdmin.tar.xz.asc --location $URL.asc; \ gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver ipv4.pool.sks-keyservers.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver keys.gnupg.net --recv-keys "$GPGKEY" \ || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY"; \ gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ tar -xf phpMyAdmin.tar.xz -C /usr/src; \ gpgconf --kill all; \ rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ mv /usr/src/phpMyAdmin-$VERSION-all-languages /usr/src/phpmyadmin; \ rm -rf /usr/src/phpmyadmin/setup/ /usr/src/phpmyadmin/examples/ /usr/src/phpmyadmin/test/ /usr/src/phpmyadmin/po/ /usr/src/phpmyadmin/composer.json /usr/src/phpmyadmin/RELEASE-DATE-$VERSION; \ sed -i "s@define('CONFIG_DIR'.*@define('CONFIG_DIR', '/etc/phpmyadmin/');@" /usr/src/phpmyadmin/libraries/vendor_config.php; \ # Add directory for sessions to allow session persistence mkdir /sessions; \ mkdir -p /var/nginx/client_body_temp; \ \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps; \ rm -rf /var/lib/apt/lists/* # Copy configuration COPY config.inc.php /etc/phpmyadmin/config.inc.php # Copy main script COPY docker-entrypoint.sh /docker-entrypoint.sh EXPOSE 8080 ENTRYPOINT [ "/docker-entrypoint.sh" ] CMD ["apache2-foreground"] |
変更点2:docker-entrypoint.shを変更します
変更前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#!/bin/bash if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then if [ "$(id -u)" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" group="${APACHE_RUN_GROUP:-www-data}" ;; *) # php-fpm user='www-data' group='www-data' ;; esac else user="$(id -u)" group="$(id -g)" fi # Custom folders for sessions chown ${user}:${group} /sessions /var/nginx/client_body_temp if ! [ -e index.php -a -e url.php ]; then echo >&2 "phpMyAdmin not found in $PWD - copying now..." if [ "$(ls -A)" ]; then echo >&2 "WARNING: $PWD is not empty - press Ctrl+C now if this is an error!" ( set -x; ls -A; sleep 10 ) fi tar --create \ --file - \ --one-file-system \ --directory /usr/src/phpmyadmin \ --owner "$user" --group "$group" \ . | tar --extract --file - echo >&2 "Complete! phpMyAdmin has been successfully copied to $PWD" mkdir -p tmp; \ chmod -R 777 tmp; \ fi if [ ! -f /etc/phpmyadmin/config.secret.inc.php ]; then cat > /etc/phpmyadmin/config.secret.inc.php <<EOT <?php \$cfg['blowfish_secret'] = '$(tr -dc 'a-zA-Z0-9~!@#$%^&*_()+}{?></";.,[]=-' < /dev/urandom | fold -w 32 | head -n 1)'; EOT fi if [ ! -f /etc/phpmyadmin/config.user.inc.php ]; then touch /etc/phpmyadmin/config.user.inc.php fi fi if [ ! -z "${HIDE_PHP_VERSION}" ]; then echo "PHP version is now hidden." echo -e 'expose_php = Off\n' > $PHP_INI_DIR/conf.d/phpmyadmin-hide-php-version.ini fi UPLOAD_LIMIT_INI_FILE="$PHP_INI_DIR/conf.d/phpmyadmin-upload-limit.ini" if [ ! -z "${UPLOAD_LIMIT}" ]; then echo "Adding the custom upload limit." echo -e "upload_max_filesize = $UPLOAD_LIMIT\npost_max_size = $UPLOAD_LIMIT\n" > $UPLOAD_LIMIT_INI_FILE fi if [ ! -z "${PMA_CONFIG_BASE64}" ]; then echo "Adding the custom config.inc.php from base64." echo "${PMA_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.inc.php fi if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then echo "Adding the custom config.user.inc.php from base64." echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php fi function get_docker_secret() { local env_var="${1}" local env_var_file="${env_var}_FILE" # Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example) # is not empty and export $PMA_PASSWORD as the password in the Docker secrets file if [[ -n "${!env_var_file}" ]]; then export "${env_var}"="$(cat "${!env_var_file}")" fi } get_docker_secret PMA_PASSWORD get_docker_secret MYSQL_ROOT_PASSWORD get_docker_secret MYSQL_PASSWORD get_docker_secret PMA_HOSTS get_docker_secret PMA_HOST exec "$@" |
変更後
39〜44行目削除(Cloud Runサービス作成時にcatで止まってしまうため。こちらの部分はDockerファイルで対応)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#!/bin/bash if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then if [ "$(id -u)" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" group="${APACHE_RUN_GROUP:-www-data}" ;; *) # php-fpm user='www-data' group='www-data' ;; esac else user="$(id -u)" group="$(id -g)" fi # Custom folders for sessions chown ${user}:${group} /sessions /var/nginx/client_body_temp if ! [ -e index.php -a -e url.php ]; then echo >&2 "phpMyAdmin not found in $PWD - copying now..." if [ "$(ls -A)" ]; then echo >&2 "WARNING: $PWD is not empty - press Ctrl+C now if this is an error!" ( set -x; ls -A; sleep 10 ) fi tar --create \ --file - \ --one-file-system \ --directory /usr/src/phpmyadmin \ --owner "$user" --group "$group" \ . | tar --extract --file - echo >&2 "Complete! phpMyAdmin has been successfully copied to $PWD" mkdir -p tmp; \ chmod -R 777 tmp; \ fi # if [ ! -f /etc/phpmyadmin/config.secret.inc.php ]; then # cat > /etc/phpmyadmin/config.secret.inc.php <<EOT #<?php #\$cfg['blowfish_secret'] = '$(tr -dc 'a-zA-Z0-9~!@#$%^&*_()+}{?></";.,[]=-' < /dev/urandom | fold -w 32 | head -n 1)'; #EOT # fi if [ ! -f /etc/phpmyadmin/config.user.inc.php ]; then touch /etc/phpmyadmin/config.user.inc.php fi fi if [ ! -z "${HIDE_PHP_VERSION}" ]; then echo "PHP version is now hidden." echo -e 'expose_php = Off\n' > $PHP_INI_DIR/conf.d/phpmyadmin-hide-php-version.ini fi UPLOAD_LIMIT_INI_FILE="$PHP_INI_DIR/conf.d/phpmyadmin-upload-limit.ini" if [ ! -z "${UPLOAD_LIMIT}" ]; then echo "Adding the custom upload limit." echo -e "upload_max_filesize = $UPLOAD_LIMIT\npost_max_size = $UPLOAD_LIMIT\n" > $UPLOAD_LIMIT_INI_FILE fi if [ ! -z "${PMA_CONFIG_BASE64}" ]; then echo "Adding the custom config.inc.php from base64." echo "${PMA_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.inc.php fi if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then echo "Adding the custom config.user.inc.php from base64." echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php fi function get_docker_secret() { local env_var="${1}" local env_var_file="${env_var}_FILE" # Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example) # is not empty and export $PMA_PASSWORD as the password in the Docker secrets file if [[ -n "${!env_var_file}" ]]; then export "${env_var}"="$(cat "${!env_var_file}")" fi } get_docker_secret PMA_PASSWORD get_docker_secret MYSQL_ROOT_PASSWORD get_docker_secret MYSQL_PASSWORD get_docker_secret PMA_HOSTS get_docker_secret PMA_HOST exec "$@" |
変更点3:Dockerfileで追加更新するapacheの設定ファイル
config.secret.inc.php※docker-entrypoint.shで削除した部分をDockerfileでファイル追加
1 2 3 4 |
<?php // a-zA-Z0-9~!@#$%^&*_()+}{?></";.,[]=- //↑の文字から32文字のランダム文字を設定してください $cfg['blowfish_secret'] = ''; |
ports.conf(port設定)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 8080 <IfModule ssl_module> Listen 443 </IfModule> <IfModule mod_gnutls.c> Listen 443 </IfModule> |
sites-available/000-default.conf(port設定とIP制限)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<VirtualHost *:8080> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName # specifies what hostname must appear in the request's Host: header to # match this virtual host. For the default virtual host (this file) this # value is not decisive as it is used as a last resort host regardless. # However, you must set it for any further virtual host explicitly. #ServerName www.example.com ServerName localhost:8080 ServerAdmin webmaster@localhost DocumentRoot /var/www/html # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. # It is also possible to configure the loglevel for particular # modules, e.g. #LogLevel info ssl:warn ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to # include a line for only one particular virtual host. For example the # following line enables the CGI configuration for this host only # after it has been globally disabled with "a2disconf". #Include conf-available/serve-cgi-bin.conf <Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride None SetEnvIf X-Forwarded-For "^192\.168\.0\.1" allow #192.168.0.224/28 SetEnvIf X-Forwarded-For "^192\.168\.0\.(22[4-9]|23[0-8])" allow Require all denied <RequireAny> Require env allow </RequireAny> </Directory> </VirtualHost> |
Cloud Runサービス作成
- コンテナイメージ:DockerfileでbuildしてContainer RegistryにPUSHしたイメージを指定します。
- 環境変数:Cloud Runで動作するアプリケーションからCloud SQLへの接続はCloud SQL Proxyを経由して接続するのでアプリケーションからUnix Socketを使って接続するため
- PMA_HOST /cloudsql/{{PROJECT_ID:REGION:INSTANCE_ID}}
- PMA_SOCKET /cloudsql/{{PROJECT_ID:REGION:INSTANCE_ID}}
- Cloud SQL接続:接続対象のCloud SQLインスタンスを選択
上記内容でサービスを作成するとphpMyAdminのサービスが作成されます。
まとめ
dockerhubのDockerfileをbuildしたイメージをそのままCloud Runのサービス作成で使用できると思ってましたがうまくいかなかったので手こずりました。
Cloud Runはコンテナで動作するため、Cloud Functionsとは違ってOS、言語を自分で決めることができて非常に使いやすいです。