A detailed tutorial on building a docker-based PHP development environment
This article focuses on building a docker-based PHP development environment for a detailed tutorial, Docker is the best choice of virtual machine technology, the need for friends can refer to the following
Many developers now use vagrant to manage their virtual machine development environment, vagrant is really cool, but there are a number of drawbacks (the main thing is that it takes up too much resources). After container technology, Docker and more Docker technologies emerge, it's easier to solve this problem.
Disclaimer
Because of the way Boot2docker works, the methods described in this article may not work correctly in your environment. If you need to share folders to Docker containers in a non-Linux environment, you need to pay more attention to the additional details. Later I will write an article specifically to introduce the actual problems encountered.
How to be a good development environment
First of all, we need to know what is a good development environment, for me, a good development environment needs to have the following characteristics:
Free to use. I must be free to delete and create a new environment.
Quick Start. When I want to work with it, it can be used immediately.
Easy to update. Things are changing very quickly in our industry, and it must be easy for me to update my development environment to a new version of the software.
And Docker supports these features, and even more. You can destroy and rebuild containers almost instantly, while updating your environment requires only rebuilding the image you are currently using.
What is a PHP development environment
At present, the Web application is complex, the PHP development environment needs a lot of things, in order to ensure the simplicity of the environment, need to do a variety of restrictions.
We use Nginx, php5-fpm, and MySQL to run the Synmfony project this time.
Pet and cattle
Another point we're going to discuss is whether we want to deploy the development environment in a multi-container or a single container. Each of the two approaches has advantages:
Single containers are easy to distribute and maintain. Because they are independent, everything runs in the same container, which is like a virtual machine. But it also means that when you want to upgrade something (like a new version of PHP), you need to rebuild the entire container.
Multiple containers can provide better modularity when adding components. Because each container contains a portion of the stack: Web, PHP, MySQL, and so on, you can extend each service individually or add services, and you don't need to rebuild everything.
Because I'm lazy, plus I need to put something else in my notebook, so here we'll just describe a single container method.
Initialize Project
The first thing to do is to initialize a new Symfony project. The recommended method is to use the composer Create-project command. You could have installed composer on your workstation, but that would be too easy. This time we use Docker for it.
I've previously sent an article about Docker commands: Make Docker commands (well, I lied, I wrote it in this article, and I thought it would be better to separate it out).
Anyway, you can read it. Next, if you don't have a composer command, you can create a composer alias that belongs to you.
?
1 |
$ alias composer= "Docker run-i-t-v \ $PWD:/srv ubermuda/composer" |
Now you can initialize the Symfony project:
?
1 |
$ composer Create-project Symfony/framwork-standard-edition Someproject |
I'm so cool! Here's some real work.
Container
It's fairly easy to build a self-contained container that runs a standard Symfony project, just install the usual nginx, php5-fpm, and Mysql-server, and then throw the pre-prepared Nginx virtual host configuration file in, Copy some of the configuration files and get in.
The source code of this container can be found in the Ubermuda/docker-symfony warehouse on GitHub. Dockerfile is the configuration file to use for the Docker build image, let's take a look at:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 |
From Debian:wheezy ENV Debian_frontend noninteractive RUN Apt-get update-y RUN apt-get install-y nginx php5-fpm php5-mysqlnd php5-cli mysql-server Supervisor RUN sed-e ' s/;d aemonize = yes/daemonize = no/'-i/etc/php5/fpm/php-fpm.conf RUN sed-e ' s/;listen\.owner/listen.owner/'-i/etc/php5/fpm/pool.d/www.conf RUN sed-e ' s/;listen\.group/listen.group/'-i/etc/php5/fpm/pool.d/www.conf RUN echo "\ndaemon off;" >>/etc/nginx/nginx.conf ADD Vhost.conf/etc/nginx/sites-available/default ADD supervisor.conf/etc/supervisor/conf.d/supervisor.conf ADD init.sh/init.sh EXPOSE 80 3306 VOLUME ["/srv"] Workdir/srv CMD ["/usr/bin/supervisord"] |
We started by extending the base image of Debian:wheezy and then configuring Nginx and PHP5-FPM through a series of SED commands.
Copy the code code as follows:
RUN sed-e ' s/;d aemonize = yes/daemonize = no/'-i/etc/php5/fpm/php-fpm.conf
RUN sed-e ' s/;listen\.owner/listen.owner/'-i/etc/php5/fpm/pool.d/www.conf
RUN sed-e ' s/;listen\.group/listen.group/'-i/etc/php5/fpm/pool.d/www.conf
RUN echo "\ndaemon off;" >>/etc/nginx/nginx.conf
We're going to do two things here. First configure PHP5-FPM and nginx to let them run in the foreground so that Supervisord can track them.
Then, configure PHP5-FPM to run Web-server with the specified user and to handle the file permissions.
Next you need to install a set of configuration files, the first is Nginx virtual host profile vhost.conf:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server { Listen 80; server_name _; Access_log/var/log/nginx/access.log; Error_log/var/log/nginx/error.log; Root/srv/web; Index app_dev.php; Location/{ Try_files $uri $uri//app_dev.php? $query _string; } Location ~ [^/]\.php (/|$) { Fastcgi_pass Unix:/var/run/php5-fpm.sock; Include Fastcgi_params; } } |
Because we don't need a domain name, so we set server_name to _ (a bit like Perl's $_ placeholder variable), and configure the root directory (document root) to/svr/web, we will deploy the application under/srv, the rest is the standard Mginx + PHP5-FPM configuration.
Because a container can only run one program at a time, we need supervisord (or any other process manager, but I prefer supervisord). Fortunately, this process manager will produce all the processes we need! Here is a small section of the Supervisord configuration:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[Supervisord] Nodaemon=true [Program:nginx] Command=/usr/sbin/nginx [PROGRAM:PHP5-FPM] command=/usr/sbin/php5-fpm [Program:mysql] Command=/usr/bin/mysqld_safe [Program:init] command=/init.sh Autorestart=false Redirect_stderr=true Redirect_stdout=/srv/app/logs/init.log |
What we need to do here is to define all the services, plus a special program:init process, which is not an actual service, but an ingenious way to run the startup script.
The problem with this startup script is that it usually needs to start some services first. For example, you might want to initialize some database tables, but if you have to run MySQL first, one possible workaround is to start MySQL in the startup script, initialize the table, and then, to prevent the process management from affecting the Supervisord, you need to stop MySQL and finally start Supervisord.
Such a script looks like this:
?
1 2 3 4 5 |
/etc/init.d/mysql start App/console doctrine:schema:update--force /etc/init.d/mysql stop Exec/usr/bin/supervisord |
It looks ugly and it's got wood, let's get supervisor to run it and never reboot.
The actual init.sh script is as follows:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/bash Ret=1 while [[Ret-ne 0]]; Do Sleep 1; Mysql-e ' exit ' >/dev/null 2>&1; Ret=$? Done Db_name=${db_name:-symfony} Mysqladmin-u Root Create $DB _name If [-N "$INIT"]; Then /srv/$INIT Fi |
The script waits for MySQL to start, then creates the DB based on the environment variable db_name, defaults to Symfony, and then finds the script to run in the INIT environment variable and tries to run it. The end of this article explains how to use these environment variables.
Build and run the image
Everything is ready only to the east wind. We'll also build the Symfony Docker image, using the Docker build command:
?
1 2 |
$ CD Docker-symfony $ docker build-t Symfony. |
Now you can use it to run your Symfony project:
?
1 2 |
$ CD Someproject $ docker run-i-t-p-v $PWD:/srv symfony |
Let's take a look at the series of options for what they do:
-I initiates the interactive (interactive) mode, which means that STDIO (standard input and output) is connected to your current terminal. It is useful when you want to receive a log or send a signal to a process.
-T creates a virtual TTY for the container, which is used in conjunction with-I as a good base friend.
-P tells the Docker daemon to publish all specified ports, in this case port 80.
-V $PWD:/srv mounts The current directory to the/srv directory of the container. Mount a directory so that directory content is available to the destination mount point.
Now you remember the db_name and INIT environment variables that you mentioned earlier, what do you do with it: to customize your environment. Basically you can set the environment variable in the container via the Docker Run's-e option, and the startup script will get the environment variable, so if your DB name is Some_project_dev, you can run the container like this:
?
1 |
$ docker run-i-t-p-v $PWD:/srv-e Db_name=some_project_dev symfony |
The INIT environment variable is even more powerful, allowing you to run the specified script when you start it. For example, you have a Bin/setup script that runs the composer Install command and sets the database schema:
?
1 2 3 |
#!/bin/bash Composer Install App/console doctrine:schema:update--force |
Run it with-e:
?
1 2 3 4 |
$ docker run-i-t-p \ -V $PWD:/srv \ -E db_name=some_project_dev \ -E Init=bin/setup |
Note that the-e option can be used multiple times in docer run and looks pretty cool. In addition, your startup script requires executable permissions (chmod +x).
Now we send the request to the container via curl to check if everything works as expected. First, we need to take the public port that Docker maps to port 80 of the container, using the Docker Port command:
?
1 2 |
$ docker Port $ (Docker PS-AQL 1) 80 0.0.0.0:49153 |
Docker PS-AQL 1 is a handy command to easily retrieve the ID of the last container, and in our case Docker maps the container's 80 port to port 49153. Let's curl up and see.
?
1 |
$ Curl http://localhost:49153 |
?
1 |
You is not a allowed to access the this file. Check app_dev.php for more information. |
When we do not access the dev controller from localhost (translator Note: container localhost), we get the default error message for Symfony, which is normal because we are not sending a curl request from inside the container, so You can safely remove these rows from the front-end controller web/app_dev.php.
?
1 2 3 4 5 6 7 8 9 |
This check prevents access to debug front controllers is deployed by accident to production servers. Feel free-remove this, extend it, or make something more sophisticated. if (Isset ($_server[' http_client_ip ')) || Isset ($_server[' http_x_forwarded_for ') || ! (In_array (@$_server[' remote_addr '), Array (' 127.0.0.1 ', ' fe80::1 ', ':: 1 ')) | | php_sapi_name () = = = ' Cli-server ') ) { Header (' http/1.0 403 Forbidden '); Exit (' is not a allowed to access the this file. Check '. basename (__file__). ' For more information. '); } |
These lines prevent any access to the dev controller from anywhere other than localhost.
Now you can work properly with curl, or access http://localhost:49153/with your browser:
http://www.bkjia.com/PHPjc/1025314.html www.bkjia.com true http://www.bkjia.com/PHPjc/1025314.html techarticle A detailed tutorial on building a docker-based PHP development environment This article introduces a detailed tutorial on building a docker-based PHP development environment, and Docker is the best choice for today's virtual machine technology .