📜 ⬆️ ⬇️

Setting up the development environment: needlework circle (Part 1)

Setting up the development environment
Hello dear reader!
Today I want to share my experience in setting up a personal environment for working with various PHP-based projects. This article describes the experience of manually setting the environment.

This article was written for my beloved to show how to simplify or complicate your life. I do not want to call for action, but only share what I encountered and what I did.

I will automate the process of deploying the environment in one of the following articles.
')
The article will be very long with a bias towards the technical side. Please under the "cat".

Prehistory


Before I begin, I want to share a little story about how it all began.

For a long time, the development process was conducted mainly on one project, with an emphasis on long-term prospects (there was a lot of work: 1 year in advance). And so it was from company to company. So it wasn’t too difficult for me to add a couple of “configs” and reload services on the local machine to add a new project. When changing the company, I just set up everything from scratch adapting to the project.

At the end of 2016, I had to switch from one project to another due to a series of very unpleasant events. Turning to a new project, it was faced with the fact that the project architecture was built in such a way that you need to simultaneously support at least 5 web services that work in conjunction. I also still have to support previous projects from time to time. And do not forget about R & D projects, Open Source projects, “hack-work”, family and children.

This set of circumstances influenced the subsequent history of my development environment and everything connected with it.

Purpose: flexible development environment for PHP-based projects


I need to get a working environment that allows me to develop, debug and research in multiple PHP-based projects with reference to the company's infrastructure.
Note: The following description refers to two projects that are now in my area of ​​responsibility: Warface Hub is what is left of it, and CryEngine Hub is the result of lightning-fast implementation, “successful” architecture and “proper” planning.

So i got the following


Resources


In large companies, Microsoft solutions are very often used to provide internal communication between employees (Outlook, Lync, AD) and even heaps of self-written applications. Since I am not too lazy to search and configure clients for Linux or use Wine, I successfully started using the “hybrid” of two OSs and virtualization:


Installing services, applications and components.


At this stage, we install everything (Guest OS) that we may need in order to raise a simple stack from Nginx, PHP and MySQL, as well as everything else that can be useful in projects (NPM, Yarn, Composer). Do not forget about our development environment and add Samba and Bind9 there.

To me it looks like this
$ sudo add-apt-repository ppa:ondrej/php $ sudo apt-get install php5.6 php7.0 php7.1 php7.1-fpm $ sudo apt-get install php-bcmath php-curl php-dev php-fpm php-gd php-intl php-json php-mbstring php-mcrypt php-mysql php-readline php-soap php-sqlite3 php-tidy php-xml php-zip php-codecoverage php-codesniffer php-common php-geoip php-igbinary php-imagick php-memcache php-memcached php-redis php-ssh2 php-xdebug php-xhrpof $ sudo apt-get install php5.6-bcmath php5.6-curl php5.6-dev php5.6-fpm php5.6-gd php5.6-intl php5.6-json php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-opcache php5.6-readline php5.6-soap php5.6-sqlite3 php5.6-tidy php5.6-xml php5.6-zip $ sudo apt-get install php7.0-bcmath php7.0-curl php7.0-dev php7.0-fpm php7.0-gd php7.0-intl php7.0-json php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-opcache php7.0-readline php7.0-soap php7.0-sqlite3 php7.0-tidy php7.0-xml php7.0-zip $ sudo apt-get install php7.1-opcache $ sudo apt-get install memcached redis-server redis-tools nginx mysql-server-5.7 mysql-client-5.7 composer npm curl nodejs nodejs-legacy ruby-full $ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - $ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list $ sudo apt-get update && sudo apt-get install yarn $ sudo gem update --system $ sudo gem install compass $ composer global require hirak/prestissimo $ sudo npm install -g grunt-cli $ sudo apt-get install bind9 samba 

Samba server


Samba server The first thing I reached out for was the Samba server , which was configured so that my IDE could work directly with the guest OS file system.

All my projects will be located on the path / var / www / {project-name}.
Also in the process of setting up the guest OS, I forcibly configured a DHCP server so that it has a static IP and hides everything behind NAT: 172.16.126.130.

$ cat /etc/samba/smb.conf
 [global] workgroup = WORKGROUP server string = %h server (Samba, Ubuntu) dns proxy = no # few changes to speed up smbd strict allocate = Yes read raw = Yes write raw = Yes strict locking = No socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072 min receivefile size = 16384 use sendfile = true aio read size = 16384 aio write size = 16384 max log size = 1000 syslog only = no syslog = 0 server role = standalone server usershare allow guests = yes [www] path = /var/www available = yes valid users = oxcom read only = no browsable = yes public = yes writable = yes executable = yes 

In order for the IDE to work with this resource, I mount this Netbios folder as a remote local disk.

Mount local drive on Windows
@echo off
@title Local UBUNTU Network Drive

net use q: \\172.16.126.130\www {user-password} /USER:oxcom

Unmount local drive
Unmount local drive
@echo off
@title Local UBUNTU Network Drive

net use q: /delete


Why did I start using Samba and not Shared Folders?
At the time when I asked this question, it turned out that Shared Folders was a directory to be mounted, and NGINX did not want to use them as the root directory of the project. The second reason was that from time to time my Shared Folders fell off for no apparent reason and without the ability to quickly restore everything. And also there is no possibility to work with symlinks, which are necessary for some npm packages and not only.

Are there any problems with IDE?
Yes, and different, but the SSD saves:


DNS server


Bind9 Dear reader can imagine how difficult it is in a large company to request small changes in network settings. And even if you successfully complete the first stage of an explanation of why you need it, the second stage (implementation) may take a very long time, which is easier to do yourself.

Since I am very lazy, after a while I’m tired of adding a record file to the hosts:
172.16.126.130 project1.lo
172.16.126.130 project2.lo


It was decided that we need a local DNS server, which can be configured faster than I can drink a bottle of German strong beer. After which a request was sent to the league of laziness. The result was not long in coming: BIND9

Setup is very simple: we describe the configuration of the forward and reverse pool of domains, and also do not forget to connect them:

$ cat /etc/bind/db.lo
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA lo. root.lo. (
0000119 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS lo.
@ IN A 172.16.126.130
@ IN AAAA ::1
* IN CNAME @

$ cat /etc/bind/db.126.16.172
;
; BIND data file for local loopback interface
;
$TTL 604800
;
; BIND reverse data file for local loopback interface
;
$TTL 604800
@ IN SOA ns.lo. root.lo. (
0000112 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS lo.

$ cat /etc/bind/named.conf.local
zone "lo" {
type master;
file "/etc/bind/db.lo";
check-names ignore;
allow-query { any; };
allow-transfer { any; };
};

zone "126.16.172.in-addr.arpa" {
type master;
file "/etc/bind/db.126.16.172";
allow-query { any; };
allow-transfer { any; };
};

$ cat /etc/bind/named.conf.options
options {
directory "/var/cache/bind";

forwarders {
8.8.8.8;
8.8.4.4;
};

recursion yes;
listen-on { any; };

auth-nxdomain no; # conform to RFC1035

listen-on-v6 { any; };
};


The server is configured. Now, for complete joy, it remains to solve a few more problems:


The result is not long in coming:

$ dig example.lo
; <<>> DiG 9.10.3-P4-Ubuntu <<>> example.lo
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32204
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.lo. IN A

;; ANSWER SECTION:
example.lo. 604800 IN CNAME lo.
lo. 604800 IN A 172.16.171.130

;; AUTHORITY SECTION:
lo. 604800 IN NS lo.

;; ADDITIONAL SECTION:
lo. 604800 IN AAAA ::1

;; Query time: 0 msec
;; SERVER: 172.16.171.130#53(172.16.171.130)
;; WHEN: Mon Jul 17 11:09:52 CEST 2017
;; MSG SIZE rcvd: 111

ping example.lo
Pinging lo [172.16.171.130] with 32 bytes of data:
Reply from 172.16.171.130: bytes=32 time<1ms TTL=64
Reply from 172.16.171.130: bytes=32 time<1ms TTL=64


That's just the "nslookup example.lo" does not work. Why, I don’t know, but any browser on the Host machine will normally go to the corresponding server.

PHP-FPM and Pools


Php It seems everything works. Now you need to start setting up PHP for each of the projects.
Working on the latest projects, it turned out that one project can consist of various services or collect many other projects in itself. That's why I got the following structure:


In the course of work, you have to use API calls between projects and it would be very good to be able to debug this all with the help of XDebug and your favorite IDE. When trying to use one PHP Pool, I encountered the following problems:


To solve this, I created my PHP Pool using a template for each project for each version of PHP. And connect them to 'include = / etc / php / 7.0 / fpm / pool.d / *. D / *. Conf'

Template
$ cat /etc/php/{php-version}/fpm/pool.d/{project-name}.d/{project-subname}.conf
 ; Start a new pool ; the variable $pool can we used in any directive and will be replaced by the ; pool name ('www' here) [{project-name}-{project-subname}] user = www-data group = www-data listen = /run/php/php7.0-$pool-fpm.sock listen.owner = www-data listen.group = www-data pm = dynamic pm.max_children = 20 pm.start_servers = 5 pm.min_spare_servers = 3 pm.max_spare_servers = 7 php_admin_value[xdebug.idekey] = key-$pool 


It looks like this:

$ ls -la /etc/php/7.0/fpm/pool.d/
cryengine.d/www.conf
cryengine.d/shop.conf
cryengine.d/forum.conf
warface.d/www.conf
www.conf
PHP Sockets List
php5.6-cryengine-www-fpm.sock
php5.6-cryengine-shop-fpm.sock
php5.6-cryengine-forum-fpm.sock
php5.6-warface-www-fpm.sock
php5.6-fpm.sock
php7.0-cryengine-www-fpm.sock
php7.0-cryengine-shop-fpm.sock
php7.0-cryengine-forum-fpm.sock
php7.0-warface-www-fpm.sock
php7.0-fpm.sock


Now each project has its own PHP Pool and xdebug.idekey, which allows you to perform continuous debugging between several projects (do not forget to configure php.ini)

Nginx


Nginx Setting up the server is pretty simple. For each project, a separate configuration file is created in 'sites-available' , which describes the vhost configuration. In the configuration, we include the appropriate configuration files for each project.

Based on the above architecture, I implemented the following structure:

$ ls -la / etc / nginx /
cryengine.d/
- www.conf
- forum.conf
- shop.conf
- ssl.conf
warface.d/
- www.conf
- ssl.conf

sites-available/
- www.cryengine.conf
- forum.cryengine.conf
- shop.cryengine.conf
- www.warface.conf

nginx.conf

$ cat /etc/nginx/sites-available/{project-subname andu.proc-nameub.conf
 server { listen 443 ssl http2; server_name {project-subname}.{project-name}.lo; root /var/www/{project-subname}.{project-name}.com/wwwroot; index index.php; error_log /var/www/{project-subname}.{project-name}.com/log/nginx.error.log error; access_log /var/www/{project-subname}.{project-name}.com/log/nginx.access.log; # configuration related to sub-project include {project-name}.d/www.conf; # global configuration for projects include {project-name}.d/ssl.conf; } 


Thus, in /etc/nginx/{project-nameki.d/ all configurations are stored that relate to the project, as well as related projects. Each project has its own PHP Pool while each version of PHP, which allows you to quickly switch between versions and only for one project.

Results


Thank you for reading to the end. I sincerely hope that manual labor has not yet died out, because the developer must be able to set up the environment himself and without automation.
As a result, I received a hybrid between the two operating systems, which allows you to fully use all the internal services of the company, as well as conduct development and debugging in an environment as close as possible to LIVE.

I understand that this is not an ideal solution, but this is one of the ways how to prepare a development environment in a short period of time.

Cons :


Pros :



Update:
Setting up the development environment: coffee grounds (Part 2)

Source: https://habr.com/ru/post/333484/


All Articles