1. Introduction

1.1 Why Docker?

Do you have a scenario where you have a project and you need to build an environment for local development, and you need to build an environment for online development, and then you go to the company and you want to poke around and build an environment, but you still have a lot of environment dependence. At this time, if you have Docker, you just need to install a Docker on the machine, put the written Dickerfile, and a line of command will automatically complete this matter, convenient and efficient, isn’t it very cool?

1.2 to prepare

Next, this article introduces how to build a PHP development environment, will use Zphal-DockerFiles as an example, this is a set of dockerfiles I prepared for my blog system.

Now whether Windows, MAC or Linux, Docker can be very good support, including Windows system, under the Win10 system Docker for Windows is actually quite good, is more eat memory.

Docker command line, we can do a lot of things, such as pulling images, running containers, executing commands in containers, etc., but now, we will use a simpler and crude way, write dockerfiles, and then manage these files through docker-compose, simplifying the operation process.

What is a Dockerfile?


Dockerfile is a script composed of a series of commands and parameters. These commands are applied to pull the base image and eventually create a new image. With Dockerfile we can create an image you need, which contains the software you want to install, which is equivalent to a customized extension to install, execute commands, etc. Then one key to execute, greatly simplifying the operation process.

To set up your environment in this article, you need to:

  • First of all, take a look at Docker and some basic operations of Docker, and what docker-compose is.
  • Then I need to install Docker and Docker-compose, which I will use to manage my Dockerfiles.

Note that writing a Dockerfile is alive, not dead, and everyone will write a different dockerfile, depending on your needs.

The official Documentation for Docker is very clear, although it is in English, it has basically everything, so it is advisable to consult for any problems: Docker Documentation

2. Start writing

The following are zphal-DockerFiles as an example, you can click the link to see the complete, the following is only snippets.

2.1 preview

First of all, let’s take a look at the dockerfile project I created, which IS roughly divided into the following directories (of course, this is my own decision, not required to format your files this way) :

zPhal-dockerfiles
    app/
        index.php
        phpinfo.php
    data/
        .gitignore
    files/
        mysql/
            conf.d/
                mysql-file.cnf
            Dockerfile
        nginx/
            conf.d/
                default.conf
                zphal.conf
            Dockerfile
            nginx.conf
        php/
            pkg/
                .gitignore
            Dockerfile
            php.ini
            php-dev.ini
            php-fpm.conf
        redis/
            Dockerfile
        docker-compose.yml
    logs/
    .gitgnore
    README.mdCopy the code

In this project, I used PHP, MySQL, Nginx, Redis; And Composer, Phalcon extension, etc.

In general, there are three processes for us to do this: to write a good dockerfile for each software; Write a configuration file; Docker-compose handles all dockerfiles, including throwing configuration profiles into the image that the dockerfile will build.

2.2 Writing a Dockerfile File

2.2.1 PHP

Here is the PHP Dockerfile:

FROM PHP :7.2-fpm MAINTAINER goozp "[email protected]" # Set the time zone ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ RUN apt-get update && apt-get install -y \ git \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install zip \ && docker-php-ext-install pdo_mysql \ && docker-php-ext-install opcache \ && docker-php-ext-install mysqli \ && rm -r COPY./ PKG /redis.tgz /home/redis.tgz COPY./ PKG /cphalcon.tar.gz /home/cphalcon.tar.gz # Install PECL extension, Here we install Redis RUN pecl install/home/Redis TGZ && echo "the extension = Redis. So" > / usr/local/etc/PHP/conf. D/Redis. Ini # Install third-party extensions, RUN CD /home \ && tar -zxvf cphalcon.tar.gz \ && mv cphalcon-* Phalcon \ && CD Phalcon /build \ && . / install \ && echo "the extension = phalcon. So" > / usr/local/etc/PHP/conf. D/phalcon. Ini # install Composer ENV COMPOSER_HOME /root/composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer ENV PATH $COMPOSER_HOME/vendor/bin:$PATH RUN rm -f /home/redis.tgz \ rm -f /home/cphalcon.tar.gz WORKDIR /data # Write Permission RUN usermod -u 1000 www-dataCopy the code

The first line defines the base image, here we use the FPM version of PHP7.2, and here the second line defines a maintainer.

Docker-composer. Yml/docker-composer. Yml/docker-composer.

services:
  php-fpm:
    volumes:
      - /etc/localtime:/etc/localtime:roCopy the code

However, when running on a non-Linux system such as Windows, we cannot fetch /etc/localtime. For greater compatibility with all platforms, I have synchronized the time to a dockerfile.

Next, install some extensions. In fact, the process of installing extensions is similar to installing PHP extensions in Linux by hand. I installed Composer directly in the image of PHP-FPM. In fact, there is also a mirror of Composer. Pulling and mirroring can also achieve the purpose, because we only use Composer to execute the command to manage our package. If Composer is a separate container, we can also turn it off when not in use. In this case, I installed composer directly into the PHP-FPM image, mainly because my project installed some PHP extensions. When I wrote the composer. Json file, I defined the extension dependencies, so that when composer is executed, the environment will check whether these dependencies are installed. So if I use composer directly, I also need to install my extension into the image, which is much more troublesome, so I do this directly in the PHP image, it really doesn’t make any difference, depending on how you use it.

2.2.2 Nginx

Here is the Nginx dockerfile:

FROM nginx:1.12 # set timezome ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime&& echo $TZ > /etc/timezoneCopy the code

This is much easier. I only set one time. Because I don’t need to install anything else, I can just use the official image.

Of course, we need to modify the configuration file, just write the configuration file in advance, and then in the docker-comemage. yml file, throw the configuration file in, we’ll talk about that, PHP configuration file, MySQL configuration file, it’s the same thing.

2.2.3 MySQL

MySQL dockerfile

FROM mysql:5.7 # set timezome ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime&& echo $TZ > /etc/timezoneCopy the code

MySQL is also nothing special, using the official mirror directly.

2.2.4 Redis

Here is Redis, also using the official image directly:

FROM redis:3.2 # set timezome ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime&& echo $TZ > /etc/timezoneCopy the code

2.3 Writing a Configuration File

How to deal with the configuration files, I have grouped the configuration files, PHP configuration files in the PHP directory, Nginx configuration in the Nginx directory, whether to create a new subfolder, such as conf.d folder.

Nginx configuration file: Nginx configuration file:

nginx/
    conf.d/
        default.conf
        zphal.conf
    Dockerfile
    nginx.confCopy the code

In addition to nginx.conf, there is also a subfolder conf.d to store all domain configuration files, which should be familiar to anyone who has set up a PHP environment under Linux. These are the configuration files that we will pass into the container at the time, and we will not use them on the host.

So the most important thing to note is that the paths that appear in configuration files are the paths of the environment inside the container, not the path of the host machine. Each container has a running environment inside it, and each is a mini-system. These paths are all paths inside the container. Docker-compose can be used for file synchronization by mounting communication to the container. To start the container from the command line, you also need to mount the file path.

Here is an example configuration file:

server { listen 80 default; index index.html index.htm; server_name localhost docker; root /data/www; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.html; } location ~ \.php { include fastcgi_params; fastcgi_pass php-fpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /data/www/$fastcgi_script_name; }}Copy the code

The root /data/ WWW path is the path of the nginx container, not the path of the current host, so we will mount the web application to this path.

2.4 write a docker – compose. Yml

In PHP, nginx, etc., we create a docker-compose. Yml. When executing the docker-compose command, we will automatically find the docker-compose file and execute it according to its contents.

Following the nginx example above, let’s talk about mounting first, because this is the most important step. In docker-comemage. yml, the nginx part:

nginx: build: ./nginx depends_on: - php-fpm links: - php-fpm:php-fpm volumes: - .. /app:/data/www:rw - ./nginx/conf.d:/etc/nginx/conf.d:ro - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - .. /logs/nginx:/var/log/nginx ports: - "80:80" - "8080:8080" - "443:443" restart: always command: nginx -g 'daemon off; 'Copy the code

The volumes parameter is the configuration of the directory we want to mount. /app is mounted to /data/ WWW, which is the default listening root defined in our configuration file, and app directory is a directory in our host. By mounting in this way, we can directly put our project files into app, docker will help you transfer to the container /data/ WWW directory.

Other parameters:

  • Build defines where your dockerfile is located. If you don’t have a dockerfile, you don’t need build. You can use images to define the official imageImage: mysql: 5.7;
  • Depends_on: nginx depends on phP-FPM. Nginx cannot play without it.
  • Links defines a connection, such as to a phP-fpm containerphp-fpm:php-fpm, followed by the alias;
  • Ports indicates port mapping.A 80-80Indicates that port 80 is mapped to port 80 of the host
  • Restart restart,restart: alwaysIndicates an automatic restart
  • Command is a command that is automatically executed
  • .

There are many parameters, more can refer to the official documentation.

Here is a complete docker-comemage.yml file:

Version: '3.2' services: PHP -fpm: build:./ PHP/ports: - mysql-db:mysql-db - redis-db:redis-db volumes: - .. /app:/data/www:rw - ./php/php-dev.ini:/usr/local/etc/php/php.ini:ro - ./php/php-fpm.conf:/usr/local/etc/php-fpm.conf:ro -.. /logs/php-fpm:/var/log/php-fpm:rw restart: always command: php-fpm nginx: build: ./nginx depends_on: - php-fpm links: - php-fpm:php-fpm volumes: - .. /app:/data/www:rw - ./nginx/conf.d:/etc/nginx/conf.d:ro - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - .. /logs/nginx:/var/log/nginx ports: - "80:80" - "8080:8080" - "443:443" restart: always command: nginx -g 'daemon off; ' mysql-db: build: ./mysql ports: - "3306:3306" volumes: - .. /data/mysql:/var/lib/mysql:rw - .. /logs/mysql:/var/lib/mysql-logs:rw - ./mysql/conf.d:/etc/mysql/conf.d:ro environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: zphaldb MYSQL_USER: zphal MYSQL_PASSWORD: zphal123 restart: always command: "--character-set-server=utf8" redis-db: build: ./redis ports: - "6379:6379" volumes: - .. /data/redis:/data restart: alwaysCopy the code

Use 3.

So how do we use it when we write it?

3.1 Use the built environment

  1. First, go to the project dockerFiles directory, here is the files directory:

    CD zPhal - dockerfiles/wget files for https://pecl.php.net/get/redis-3.1.6.tgz - PHP/O PKG/redis TGZ wget https://codeload.github.com/phalcon/cphalcon/tar.gz/v3.3.1 - O PHP/PKG/cphalcon. Tar. GzCopy the code

    Then download the PHP extensions that we’ll be using.

  2. Execute command:

    docker-compose upCopy the code

    Docker automatically builds an image from the docker-comemess.yml content written and starts the container. If no problem, the next startup can be enabled in daemon mode, all containers will run in the background:

    docker-compose up -dCopy the code
  3. You can close the container and delete the service by:

    docker-compose downCopy the code

Docker-compose is basically as simple as that, manipulating container services with stop, start, etc. The more work is in writing dockerfile and docker-comemage.yml files.

3.2 using Composer

What do we do when we want to use Composer? We have already installed Composer in phP-FPM.

Docker-compose

docker-compose run --rm -w /data/www/zPhal php-fpm composer updateCopy the code

-w /data/ WWW /zPhal is the work area in phP-FPM, zPhal project is also mounted in it, so we can run composer directly in the container.

Or enter the host app directory and use the docker command:

cd zPhal-dockerfiles/app

docker run -it --rm -v `pwd`:/data/www/ -w /data/www/zPhal files_php-fpm composer updateCopy the code

4. Precautions

  • Pay attention to the mount path
  • Note if any errors are reported in the container when the build fails
  • Accelerated mirroring. If the process is slow to download the image, you can use domestic accelerated image services such as Alicloud, Daocloud.

This article started on my blog: Building your own PHP development environment with Docker freehand