Docker - Pass a environment setting via docker-compose - php

I am new to Docker and have a working docker-compose file, apart from one part. What I want to achieve is to set an environment setting so that in my PHP application I can use some variables to determine which resources I load in.
In MAMP PRO, for instance, you can access environment settings on this page:
.
In my docker-compose file I have the following:
services:
webserver:
build: ./docker/webserver
image: perch
ports:
- "80:80"
- "443:443"
volumes:
- C:/websites/sitename/www:/var/www/html
links:
- db
environment:
- DEVELOPER_ENV=development
At the moment the variable - from what I can tell - isn't being set as my php variables to detect the environment, fail. Any pointers would be appreciated.

Apache by default removes most environment variables for security reasons.
But you can whitelist variables in the etc/apache2/conf-enabled/expose-env.conf file.
So I added theses commands to my dockerfile:
RUN
echo 'PassEnv DB_PW' >> /etc/apache2/conf-enabled/expose-env.conf \
&& echo 'PassEnv DB_USER' >> /etc/apache2/conf-enabled/expose-env.conf
Alternatively you can copy or mount the expose-env.conf.

Related

How to log to a file from a dockerized php app

I have a php app dockerized.
My issue is how to capture errors from php service into a dedicated file on the host.
docker file looks is next:
version: "3.9"
services:
web:
image: nginx:latest
ports:
- "3000:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./public:/public
php:
build:
context: .
dockerfile: PHP.Dockerfile
environment:
APP_MODE: 'development'
env_file:
- 'dev.env'
volumes:
- ./app:/app
- ./public:/public
- ./php.conf:/usr/local/etc/php-fpm.d/zz-log.conf
mysql:
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: <pass here>
env_file:
- 'dev.env'
volumes:
- mysqldata:/var/lib/mysql
- ./app:/app
ports:
- '3306:3306'
volumes:
mysqldata: {}
my php.conf that maps as /usr/local/etc/php-fpm.d/zz-log.conf inside php service looks like bellow:
php_admin_value[error_log] = /app/php-error.log
php_admin_flag[log_errors] = on
catch_workers_output = yes
My intention is using php error_log() function and have all the logs recorded in php-error.log which is a file inside volume app.
Now, all logs from containers are shown on terminal only.
I have been struggling with this several hours and have no ideea how to continue. Thank you
I don't know what is your source image. I assume some official docker image for PHP like https://hub.docker.com/_/php
All containerized applications are usually configured to log to stdout so you must override that behaviour. This is really PHP specific and I'm no PHP expert. From what you let us know it looks like you know how to override that behaviour (by using some error_log() function and php_admin_value[error_log] = /app/php-error.log property.
If the behaviour is overridden you should ensure the file app/php-error.log exists inside of the PHP container (i.e. get inside the container by something like docker exec -it my-container-id /bin/bash and then do ls /app/php-error.log and cat /app/php-error.log to see if the file is created.
Because you're mounting the ./app directory from the host to /app directory in container you already have them mirrored. Whatever is inside container's /app you will find in also your /path/to/docker/compose/app directory. You can check if file exists and some content is inside. If not you failed to override the default behaviour of where PHP is logging to.

Use Docker env vars with PHP 5.2.x

I have inherited some code that was written with PHP 5.2, and rather than installing myself, I have it running in a Docker container.
This system also depends on MySQL, so using Docker Compose and extracting the database credentials to a more secured location...
version: "3"
services:
mariadb:
image: mariadb:10.5
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
volumes:
- ./conf/mariadb/initdb.d:/docker-entrypoint-initdb.d/:ro
ports:
- "3306:3306"
nginx:
image: nginx:alpine
depends_on:
- php-fpm
volumes:
- ${LOCAL_WORKING_DIR}:${REMOTE_WORKING_DIR}
- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./conf/nginx/conf.d/:/etc/nginx/conf.d/
# - ./conf/nginx/ssl/:/etc/nginx/ssl/
ports:
- "8080:80"
# - "8443:443"
php-fpm:
build:
context: docker/app
args:
APP_ENV: ${APP_ENV}
PHP_VERSION: ${PHP_VERSION}
REMOTE_WORKING_DIR: ${REMOTE_WORKING_DIR}
depends_on:
- mariadb
working_dir: ${REMOTE_WORKING_DIR}
volumes:
- ${LOCAL_WORKING_DIR}:${REMOTE_WORKING_DIR}
- ./conf/php/www.conf:/usr/local/etc/php-fpm.d/www.conf:ro
# - ./conf/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini:ro
- ./conf/php/php-ini-overrides.ini:/usr/local/etc/php/conf.d/99-overrides.ini:ro
environment:
DB_HOST: mariadb:3306
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_DATABASE: ${DB_DATABASE}
ports:
- "9000:9000"
Dockerfile
FROM devilbox/php-fpm:5.2-base
EXPOSE 9000
CMD ["php-fpm"]
Using phpinfo() shows none of those values in $_ENV or $_SERVER, and getenv() returns empty strings.
I have seen latest php-fpm related issues saying this is solved with clear_env: no, but this is only available in PHP-FPM 5.4+
I have tried to use composer to install dotenv, but that seemed to require PHP7. Same for trying to install Vault to read database credentials remotely.
What else could I try to get this code to run as-is with minimal changes?
Options I have thought:
Start up a secondary REST server that exposes a preconfigured environment, then request to that from PHP... Seems hacky, but better than hard-coding database creds in any code, and would achieve a similar result as using Vault.
Mount my .env file, then parse it out, but that requires more code changes that would be removed later anyway
I found an XML file at /usr/local/etc/php-fpm.conf that contained the Environment variables, and filled it in using dockerize
<value name="environment">
<!-- Add docker environment variables -->
{{ range $k,$v := .Env }}{{ $parts := split $k "APP_" }}{{ if eq (len $parts) 2 -}}
<value name="{{ index $parts 1 }}">{{ $v }}</value>
{{ end }}{{- end -}}
<!-- End Docker Env -->
With docker-compose having
environment:
APP_DB_HOST: mariadb:3306
APP_DB_USER: ${DB_USER}
APP_DB_PASSWORD: ${DB_PASSWORD}
APP_DB_DATABASE: ${DB_DATABASE}
most probably those env are overridden somewhere in image you are using.
docker compose allows to define a command to run on startup. So you can override env vars on startup to whatever you need:
command: bash -c "DB_HOST='mariadb:3306' && DB_USER='some_user ... & ./start_something.sh"
EDIT:
as comment mentioned php require all env to be in php-fpm.conf. strange as for me but it's easy enough to work around by adding env vars you need into this file in same command: statement of docker compose. Simple echo "ENV_NAME" >> ..../php-fpm.conf should help you.
or you can modify Dockerfile so your image has simple sh script which would dump all env vars into that php config.
i am modifying mongo config so works as replica set - works like a charm.

Access to docker container like an URL

I have an application developed with PHP, Nginx and dynamodb. I have create a simple docker-compose to work in local.
version: '3.7'
services:
nginx_broadway_demo:
container_name: nginx_broadway_demo
image: nginx:latest
ports:
- 8080:80
volumes:
- ./www:/var/www
- ./docker/nginx/vhost.conf:/etc/nginx/conf.d/default.conf
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
links:
- php_fpm_broadway_demo
php_fpm_broadway_demo:
container_name: php_fpm_broadway_demo
build:
context: ./docker/php
ports:
- 9000:9000
volumes:
- .:/var/www/web
dynamodb:
image: amazon/dynamodb-local
ports:
- 8000:8000
expose:
- 8000
Now I need to add dynamodb URL params to allows PHP to make queries to the database.
So, if I make a ping from PHP docker container like this works fine:
ping dynamodb
This doesn't work.
ping http://dynamodb:8000
I need to use http://dynamodb:8000 because AWS needs a URI because I have this error if I use http://dynamodb:8000:
Endpoints must be full URIs and include a scheme and host
So: how can I call a docker container like an URL?
I have tried with docker-compose parameters like: depends, links, network without success
As discussed in the chat, the error come when dependency installed on the host and use inside the container as composer work base on the underlying platform.
So we investigate that the issue come due to above reason. installing dependency inside the container fix the issue.
docker exec -it php bash -c "cd web; composer install"

PhpStorm multi-docker hostname resolution

I have a fully set up docker environment furnished with Xdebug, properly set up with PhpStorm. My environment has multiple containers running for different functions. All appears to work great. CLI/Web interaction both stop at breakpoints as they should, no problems. However ...
I have a code snippet as follows:
// test.php
$host = gethostbyname('db'); //'db' is the name of the other docker box, created with docker-compose
echo $host;
If I run this through bash in the 'web' docker instance:
php test.php
172.21.0.2
If I run it through the browser:
172.21.0.2
If I run it via the PhpStorm run/debug button (Shift+F9):
docker://docker_web:latest/php -dxdebug.remote_enable=1 -dxdebug.remote_mode=req -dxdebug.remote_port=9000 -dxdebug.remote_host=172.17.0.1 /opt/project/test.php
db
It doesn't resolve! Why would that be, and how can I fix it?
As it happens, my docker environment is built with docker-compose, and all the relevant containers are on the same network, and have a proper depends_on hierarchy.
However. PHPStorm was actually set up to use plain docker, rather than docker-compose. It was connecting fine to the docker daemon, but because the container wasn't being build composer-aware, it wasn't leveraging the network layout that was defined in my docker-compose.yml. Once I told PHPStorm to use docker-compose, it worked fine.
As an aside, I noticed that after I run an in-IDE debug session after already loading my container, and causes the container to exit when the script ends. To get around this, I had to create a mirror debug container for PHPStorm to use on demand. My config is as follows:
version: '3'
services:
web: &web
build: ./web
container_name: dev_web
ports:
- "80:80"
volumes:
- ${PROJECTS_DIR}/project:/srv/project
- ./web/logs/httpd:/var/log/httpd
depends_on:
- "db"
networks:
- backend
web-debug:
<< : *web
container_name: dev_web_debug
ports:
- "8181:80"
command: php -v
db:
image: mysql
container_name: dev_db
ports:
- "3306:3306"
volumes:
- ./db/conf.d:/etc/mysql/conf.d
- ./db/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
networks:
- backend
networks:
backend:
driver: bridge
This allows me to be able to do in-IDE spot debuging on the fly without killing my main web container.

How to increase load time on docker with nginx and php7-fpm on local machine

On my local machine, WordPress Page load time is very slow on docker with nginx and php7-fpm and in network call its shows 2 - 4 sec to load first doc. but when I calculate PHP execution time it shows me 0.02 - 0.1 sec. how can I optimize docker setup to speed up the local environment?
below are some details of my local environment
My Local Environment is set up on Mac Sierra and I run the docker by
docker-compose up -d
and here is my docker-compose.yml file
version: '2'
services:
mysql:
container_name: db
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=dummy
- MYSQL_DATABASE=dummy
- MYSQL_USER=dummy
- MYSQL_PASSWORD=dummy
volumes:
- dummy_path/dump.sql.gz:/docker-entrypoint-initdb.d/sql1.sql.gz
nginx:
container_name: nginx
image: nginx:latest
ports:
- "80:80"
- "443:443"
links:
- mysql:db
- php
volumes:
- dummy_path:/app/www
- dummy_path/nginx/conf.d/:/etc/nginx/conf.d/
- dummy_path/nginx/ssl:/etc/ssl/
- dummy_path/nginx/nginx.conf/:/etc/nginx/nginx.conf
- dummy_path/hosts:/etc/hosts
php:
container_name: php
image: droidhive/php-memcached
links:
- mysql:db
- memcached
volumes:
- dummy_path:/app/www
- dummy_path/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini
- dummy_path/hosts:/etc/hosts
memcached:
container_name: memcached
image: memcached
volumes:
- dummy_path:/app/www
First thing I would try is to update your Dockerfile to ADD or COPY all your files into each image rather than mounting them as volumes. #fiber-optic mentioned this in the comments, but the new Dockerfile for your PHP container would be something like this:
FROM droidhive/php-memcached
ADD dummy_path:/app/www
ADD dummy_path/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini
ADD dummy_path/hosts:/etc/hosts
Do this for at least the PHP container, but the MySQL container might also be an issue.
If that doesn't help or you can't get it to work, try adding :ro or :cached to each of your volumes.
:ro means "read-only", which allows your container to assume the volume won't change. Obviously this won't work if you need to do local dev with the code in a volume, but for some of your configuration files this will probably be fine.
:cached means that the host's files are authoritative, and the container won't constantly be checking for updates internally. This is usually ideal for code that you're editing on your host.

Categories