Giter Site home page Giter Site logo

yii2-dockerized's Introduction

Yii 2 Dockerized

A template for docker based Yii 2 applications.

  • Ephemeral container which gets configured via environment variables
  • Optional local configuration overrides for development/debugging (git-ignored)
  • Base scaffold code for login, signup and forgot-password actions
  • Flat configuration file structure
  • Support docker image based development workflow
  1. Creating a new project

To use this template, you first need to have docker (>=1.5.0) installed. Then you can start a new project with:

composer create-project --no-install codemix/yii2-dockerized myproject

or, if you don't have composer installed, download and uncompress the files into a directory. You may then want modify some things to match your project requirements:

  • the Dockerfile e.g. to enable more PHP extensions.
  • the default machine setup in .docker-composer-example
  • the default configuration in config/
  • the dependencies in composer.json (requires update of composer.lock, see FAQ below)
  • the example models and initial DB migration
  • the available environment variables
  • the README (this file ;) )

When you're done, you should commit your initial project to your git repository.

  1. Setting up the development environment

For local environments we recommend to use docker-compose. Then bringing a new developer into the project is a matter of a few simple steps:

  • Clone the app sources from your repository
  • Create a local docker-compose.yml configuration file (see docker-compose-example.yml)
  • Add ENABLE_ENV_FILE=1 to the environment section of your docker-compose.yml
  • Copy the .env-example file to .env
  • Run DB migrations (see below)

Now the app can be started with docker-compose up and should be available under http://localhost:8080 (or the IP address of your VM if you use boot2docker).

As this template follows the 12 factor principles, all runtime configuration should happen via environment variables. So in production, you will use env vars e.g. to pass DB credentials to your container.

For local development you could configure those vars in the environment section of your docker-compose.yml. But this requires to rebuild the container whenever you change any var. That's why we prefer .env files (using phpdotenv) for local development. The app will pick up any changes there immediately.

The template so far uses the following configuration variables:

  • ENABLE_ENV_FILE whether to load env vars from a local .env file. Default is 0.
  • ENABLE_LOCALCONF whether to allow local overrides for web and console configuration (see below). Default is 0.
  • YII_DEBUG whether to enable debug mode for Yii. Default is 0.
  • YII_ENV the Yii app environment. Either prod (default) or dev
  • YII_TRACELEVEL the traceLevel to use for Yii logging. Default is 0.
  • COOKIE_VALIDATION_KEY the unique cookie validation key required by Yii. This variable is mandatory.
  • DB_DSN the DSN to use for DB connection. If this is not set, it will try to create one from docker's DB_PORT_3306_TCP_ADDR and assume MySQL as DBMS and web as DB name. If this is not set either, an exception is thrown.
  • DB_USER the DB username. Defaults to web if not set.
  • DB_PASSWORD the DB password. Defaults to web if not set.
  • SMTP_HOST the SMTP hostname.
  • SMTP_USER the username for the SMTP server.
  • SMTP_PASSWORD the password for the SMTP server.
  1. Configuration files

All configuration lives in 3 files in the config/ directory.

  • web.php configuration of the web app
  • console.php configuration of the console app (reused parts of web.php, see examples)
  • params.php application parameters for both web and console application

For maximum flexibility you can also use local overrides for web and console configuration files. You therefore first need to set the ENABLE_LOCALCONF variable to 1 in your docker-compose.yml or .env file. Then the app will check if any of the following files exists:

  • local.php optional local overrides to the web config
  • console-local.php an optional file with local overrides to the console configuration

Both have the same format as web.php and console.php and are merged into the respective configuration. So you only have to add those parts of the configuration that differ from the web.php and console.php. The files are ignored by git to not accidentally commit any local configs.

  1. Workflows

Docker is very versatile so you can come up with different workflows.

4.1 Dockerfile based

  • No docker registry required
  • Slower deployment due to extra build step

This is a very simple workflow: In each environment the runtime image is built from the Dockerfile. Developers need to be informed whenever the Dockerfile changes so that they rebuild their local image.

No images are shared, so the build step could take quite some time, depending on how much the Dockerfile has changed since the last build in this environment.

4.2 Docker image based

  • Requires a docker registry (either self-hosted or from 3rd party)
  • Quick and simple deployment

Here we can take two approaches: With or without a base image. In both cases the Dockerfile should be organized in a way, that the "static", less changing parts should be on top of the Dockerfile and the "variable" or frequently changing parts (e.g. COPY . /var/www/html) are on the bottom of the file.

4.2.1 Without a base image

We use a single Dockerfile and each time we want to make a deployment, we create a new tagged image and push it to the registry. This image can then be pulled to production.

One drawback here is, that each deployment image contains a full copy of your source code, even if you only changed a couple of lines since the last deployed image.

It's also important that the developers alway pull the last deployed image to their machine, as otherwhise docker couldn't reuse cached layers the next time it builds a new image.

4.2.2 Using a base image

Here we use two Dockerfiles:

  • One for the base image, e.g. Dockerfile.base and
  • one for the final image, which extends from the base image

So we'd first move the current Dockerfile and create a base image:

mv Dockerfile Dockerfile.base
docker build -f Dockerfile.base -t myregistry.com:5000/myapp:base-1.0.0
docker push myregistry.com:5000/myapp:base-1.0.0

Now we have a base image as version base-1.0.0. For ongoing development we take it from there and use a minimal second Dockerfile that is based on this image:

FROM myregistry.com:5000/myapp:base-1.0.0
COPY composer.json /var/www/html/
COPY composer.lock /var/www/html/
RUN composer self-update && \
    composer install --no-progress
COPY . /var/www/html
RUN mkdir runtime web/assets \
    && chown www-data:www-data runtime web/assets

So other developers will now use this simplified Dockerfile for their daily work. They don't have to rebuild all the layers from the base image and will only stack their local changes on top.

We'll also use this file for the final deployment images:

docker build -t myregistry.com:5000/myapp:1.0.0
docker build -t myregistry.com:5000/myapp:1.0.1
docker build -t myregistry.com:5000/myapp:1.0.2
...

After some time, when the modifications to the base-1.0.0 image exceed a certain volume, we can create another base image:

docker build -f Dockerfile.base -t myregistry.com:5000/myapp:base-1.1.0
docker push myregistry.com:5000/myapp:base-1.1.0

And modify the FROM line in the Dockerfile to use this image as basis:

FROM myregistry.com:5000/myapp:base-1.1.0
  1. FAQ

5.1 How can i run yii console commands?

docker-compose run --rm web yii migrate
docker-compose run --rm web yii mycommand/myaction

5.2 Where are composer packages installed?

Composer packages are installed inside the container but outside of the shared directory. During development we usually mount the local app directory into the container and override any files there. So we would either have to locally install all the packages in vendor/ (requiring a local composer installation) or somehow make sure, that the composer packages are updated after the local dir was shared.

By keeping the directory outside, we circumvent this issue. Docker images will always contain all required composer dependencies and use those at runtime.

5.3 How can I update or install new composer packages?

To update or install new packages you first need an updated composer.lock file. Then the next time you issue docker-compose build (or manually do docker build ...) it will pick up the changed file and create a new docker image with the updated packages.

Due to the nasty API rate limitation on github, you can't just run composer inside our web container. You first have to create a personal API token at github and expose it in your docker-compose.yml file as API_TOKEN env var.

Then use our custom composer wrapper script as follows (Note the important ./ before the composer command):

docker-compose run --rm web ./composer update my/package

Now you should have an updated composer.lock file and can rebuild your container:

docker-compose build

5.4 I have a permission issue with runtime / web/assets directory. How to fix it?

This is caused by a missing feature in docker: You can not set the permissions of shared volumes. As a workaround make the directories world writeable:

chmod a+rwx runtime/ web/assets/

5.5 How can I log to a file?

The default log configuration follows the Docker convention to log to STDOUT and STDERR. You should better not change this for production. But you can use a local configuration file as explained above and configure a log route as usual. If you log to the default directory, you should find the logfiles in your local runtime/logs/ directory. Note, that this directory will never be copied into the container, so there's no risk, that you end up with a bloated image.

yii2-dockerized's People

Contributors

mikehaertl avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.