The original link

If you are interested or interested in US stocks, you can add me on wechat: Xiaobei060537, and communicate with me at 😝.

1. Introduction

1.1 Why use Docker?

Is there a scenario where you have a project, you need to build an environment when you’re developing it locally, you need to build an environment when you’re putting it online, and you want to go to the company and play with it, and you need to build an environment, and you don’t need to build an environment, because your environment depends on so much. At this time, if there is Docker, only need to install a Docker on the machine, put the written Dickerfile, a line of command to automatically complete this thing, convenient and efficient, isn’t it very cool?

1.2 to prepare

Next, this article describes how to build a PHP development environment, using zphal-DockerFiles as an example, which 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, in Win10 system Docker for Windows is actually very good, is more eat memory.

Through the Docker command line, we can do a lot of things, such as pulling images, running containers, executing commands inside containers, etc. But now, we need to write dockerfiles in a more simple and crude way, and then manage these files through docker-compose to simplify 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. Through Dockerfile, we can create an image you need, which contains the software you want to install, which is equivalent to pre-customized extensions to install, execute commands and so on. Then one-click execution, greatly simplifying the operation process.

To set up the environment in this article, you need:

  • First, learn about 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 writes a different dockerfile, depending on your needs.

Docker’s official Documentation is very clear, although in English, but basically everything, there are issues on Documentation is very wise to turn over: Docker Documentation

2. Start writing

The following are all Zphal-DockerFiles as an example, you can click the link to see the complete, the following is just a fragment.

2.1 preview

First of all, let’s take a look at the dockerFile project I created, which I roughly divided into the following directories (of course this is my own, not required to layout 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.md
Copy the code

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

In general, we do this in three steps: write the dockerfile for each software; Write a configuration file; Process all dockerfiles via docker-compose, including throwing configuration profiles into the image that the dockerfile file will build.

2.2 Writing the Dockerfile file

2.2.1 PHP

Here is the PHP Dockerfile:

FROM php:7.2-fpm
MAINTAINER goozp "[email protected]"# Set time zoneENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ> /etc/timezonePHPThe core developmentRUN 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 /var/lib/apt/lists/ * # will advance downloaded to expand package copied into the COPY from the host machine. / PKG/redis.tgz/home/redis TGZ COPY. / PKG/cphalcon. Tar. Gz/home/cphalcon tar. Install PECL gz # Development, 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, Here is the Phalcon extension 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 the second line defines a maintainer.

The time zone is defined in every dockerfile in order to synchronize the time of all containers with the host. In fact, we can define this in docker-Composer.

services:
  php-fpm:
    volumes:
      - /etc/localtime:/etc/localtime:ro
Copy the code

However, when running on non-Linux systems, such as Windows, we can’t get /etc/localtime. For greater compatibility with all platforms, I write the time synchronization to dockerfile.

The next step is to install some extensions. In fact, the process of installing extensions is similar to that of installing PHP extensions in Linux by hand, except for Composer. I directly installed the Composer in the image of PHP-Fpm, in fact, the official also provides the image of Composer, and pulling the Composer image for execution can also achieve the purpose, because we only use Composer to execute the Composer command to manage our packages. If composer is a container on its own, we can close the container when not in use. However, in this case, I directly install the composer into the PHP-fpm image. The main reason is that some PHP extensions have been installed in my project. When writing the composer. So if I use Composer directly, I need to install the extension I’m using into the image, which is a lot of trouble, so I just do this in the PHP image, it doesn’t really make a 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/timezone
Copy the code

This one 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, as long as we write the configuration file in the docker-compose.

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/timezone
Copy the code

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

2.2.4 Redis

Here’s Redis, also using the official image:

FROM redis:3.2

#  set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
Copy the code

2.3 Writing configuration files

The PHP configuration files are stored in the PHP directory, and the Nginx configuration files are stored in the Nginx directory. It is up to you to create a new subfolder, such as conf.d.

The Nginx directory looks like this:

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

In addition to nginx.conf, there is a subfolder conf.d that holds all the domain name configuration files, which should be familiar to those who have set up PHP on Linux. These configuration files are the ones that we’re going to pass into the container, and we’re not going to use them on the host.

So the most important thing to note is that the paths that appear in the configuration file are the paths inside the container, not the paths of the host. Every container has a running environment, which is a small system, and these paths are the paths inside the container. We can synchronize files by communicating with the container by mounting it. Starting the container on the command line also requires mounting the file path, which we do now with docker-compose.

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

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

2.4 write a docker – compose. Yml

In PHP, nginx, and other directories, we create a file called docker-compose. Yml. When we run the docker-compose command, we automatically find this file and execute based on its contents.

Following the nginx example above, let’s talk about mounting first, because this is the most important step. In docker-compose. 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

There is a volume parameter. Here 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 the app directory is a directory in our host machine, through this mounting we can directly put our project files into the app, Docker will help you transfer to the container /data/ WWW directory.

Other parameters:

  • Build defines where your dockerfile is. If you don’t have a dockerfile, you don’t need to build. You can define an official image using the images parameterImage: mysql: 5.7;
  • Depends_on – nginx is dependent on phP-fpm – nginx cannot play without it
  • Links Defines connections, such as to connect to the PHP-fpm containerphp-fpm:php-fpm, followed by an alias;
  • Ports indicates port mapping.A 80-80Port 80 is mapped to port 80 on the host
  • Restart restart,restart: alwaysIndicates that the system automatically restarts
  • Command is the command that is automatically executed

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

Here’s a complete docker-compose. Yml file:

version: '3.2'
services:
  php-fpm:
    build: ./php/
    ports:
      - "9000:9000"links: - 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 if we write this down, how do we use it?

3.1 Using the Established Environment

  1. First, go to the project dockerFiles directory, here is the files directory:
cd zPhal-dockerfiles/files

 wget https:/ / pecl.php.net/get/redis-3.1.6.tgz -o PHP/PKG/redis TGZ
 wget https:/ / codeload.github.com/phalcon/cphalcon/tar.gz/v3.3.1 -o PHP/PKG/cphalcon tar. Gz
Copy the code

Then download the PHP extension package that we will use.

  1. Execute command:
docker-compose up
Copy the code

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

docker-compose up -d
Copy the code
  1. To close the container, you can do this:
docker-compose down
Copy the code

Using Docker-compose is basically as simple as manipulating the container service with commands like stop, start, etc. The more work is in writing the dockerfile and docker-compose. Yml file.

3.2 using Composer

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

Operate with docker-compose:

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

-w /data/ WWW /zPhal -w /data/ WWW /zPhal -w /data/ WWW /zPhal -w /data/ WWW /zPhal -w /data/ WWW /zPhal -w /data/ WWW /zPhal -w /data/ WWW /zPhal

Or go to 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 update
Copy the code

4. Precautions

  • Pay attention to the mount path
  • When the build fails, pay attention to whether an error is reported in the container
  • Accelerate the mirror image. If the process is slow to download images, use a domestic accelerated image service, such as Ali Cloud or Daocloud.