Deploy LNMP+Redis environment using Docker

Docker profile

Docker is an open source application container engine that allows developers to package their applications and dependencies into a portable container and then distribute them to any popular Linux machine, as well as virtualization. Containers are completely sandboxed and have no interface with each other. Kernel version 3.8 or later is recommended

Why Docker

  1. Accelerating the local development and build process, containers can be built in the development environment, then easily committed to the test environment, and eventually to production
  2. The ability to have separate services or applications run in different environments with the same results
  3. Create an isolated environment for testing
  4. High-performance, super-planned host deployment
  5. Build from scratch or extend existing OpenShift or Cloud Foundry platforms to build your own PaaS environment

directory

  • Install the Docker
  • The directory structure
  • Quick to use
  • Inside the container
  • PHP Extension Installation
  • Composer installation
  • Common Problem Handling
  • Common commands
  • Dockerfile grammar
  • Docker-compose syntax description

Project source address :GitHub

Install the Docker

Windows installation

reference

mac

Docker toolbox reference

linux

# Download and install
curl -sSL https://get.docker.com/ | sh

# Set boot to boot
sudo systemctl enable docker.service

sudo service docker start|restart|stop

# installation docker - composeThe curl -l https://github.com/docker/compose/releases/download/1.23.2/docker-compose- ` uname-s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
Copy the code

The directory structure

├── ├─ ├─ all exercises, ├─ all exercises, all exercises, all exercises, all exercises, all exercises, all exercises, all exercises, all exerciseslog│ │ └ ─ ─ the error. The log │ └ ─ ─ WWW │ ├ ─ ─ index. The HTML │ ├ ─ ─ index. The PHP │ ├ ─ ─ the PHP │ └ ─ ─ redis. PHP ├ ─ ─ PHP │ ├ ─ ─ Dockerfile │ ├ ─ ─ www.conf │ ├─ ├─ php-fpmlog│ └ ─ ─ PHP - FPM. Log └ ─ ─ redis └ ─ ─ Dockerfile └ ─ ─ redis. ConfCopy the code

Image creation and installation

Use Docker-compose directly to create a one-click image and start the container

Version of a

This version is by pulling clean CentOS image, through the Dockerfile command source code compilation install each service. Therefore, this method is convenient to customize the image you need, but it takes up a lot of space and is slow to build.

git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp
docker-compose up -d
Copy the code

Version 2 (Recommended)

git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp/v2
chmod 777 ./redis/redis.log
chmod -R 777 ./redis/data
docker-compose up -d
Copy the code

This version is by pulling the official has produced each service image, and then through the Dockerfile related commands according to their own needs to do the corresponding adjustment. So it’s quick to build and easy to use, and takes up very little space because it’s based on Alpine Linux.

test

127.0.0.1/index.php, 127.0.0.1/db.php, 127.0.0.1/redis.php, 127.0.0.1/redis.php (If you want to use HTTPS, please modify the dockerfile under nginx and nginx.conf as the prompt to remove the comment, you need to add your own certificate file in SSL folder, this project is empty, you need to replace, keep the same file name.)

Inside the container

  1. Use the docker exec
docker exec -it ngixn /bin/sh
Copy the code
  1. Use the nsenter command
# cd /tmp; The curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar ZXF -; CD util - Linux - 2.24;
# ./configure --without-ncurses
# make nsenter && sudo cp nsenter /usr/local/bin
Copy the code

To connect to the container, you also need to find the PID of the container’s first process, which can be obtained by executing the command below.

PID=$(docker inspect --format "{{ .State.Pid }}" container_id)
# nsenter --target $PID --mount --uts --ipc --net --pid
Copy the code

PHP Extension Installation

  1. Install the pdo_mysql mysqli PCNTL gd extension.

Add the following command to the PHP Dockerfile

RUN apk add libpng-dev \
    && docker-php-ext-install pdo_mysql mysqli pcntl gd \
Copy the code

Note: Since this image lacks the libpng-dev package required by the GD library, you need to download this package first

  1. PECL expansion installation
# Install extension
RUN pecl install memcached-2.2.0 \
    # enable extension
    && docker-php-ext-enable memcached \
Copy the code
  1. By downloading the extended source code, compile and install the way to install
# Install Redis and Swoole extensions
RUN cd~ \ && wget https://github.com/phpredis/phpredis/archive/4.2.0.tar.gz \ && tar - ZXVF 4.2.0. Tar. Gz \ && mkdir -p /usr/ SRC/PHP /ext \ && mv phpredis-4.2.0 /usr/ SRC/PHP /ext/redis \ && docker-php-ext-install redis \ && apk add libstdc++\ &&cd~ \ && wget https://github.com/swoole/swoole-src/archive/v4.2.12.tar.gz \ && tar - ZXVF v4.2.12. Tar. Gz \ && mkdir -p /usr/ SRC/PHP /ext \ && mv swoole-src-4.2.12 /usr/ SRC/PHP /ext/swoole \ && docker-php-ext-install swoole \Copy the code

Note: because the image requires the swoole dependent libstdc++ to be installed first, otherwise the swoole extension will not load properly after a successful installation

Composer installation

Add to Dockerfile

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \
Copy the code

Common Problem Handling

  • Redis startup failure In v2, the redis startup user is redis, not root. Therefore, write permission is required for the./redis/redis.log and./redis/data files mounted on the host.

       chmod 777 ./redis/redis.log
       chmod 777 ./redis/data
    Copy the code
  • Caching_sha2_password is the latest version of MySQL8. Caching_sha2_password is the latest version of MySQL8. Caching_sha2_password is the latest version of MySQL8, and Caching_sha2_password is the latest version of MySQL8 Plugins check whether the authentication mode is supported. Otherwise, change the authentication mode to the original one. Mysql_native_password:

        select user,host,plugin,authentication_string from mysql.user;
        ALTER USER 'root'@The '%' IDENTIFIED WITH mysql_native_password BY '123456';
        FLUSH PRIVILEGES;
    Copy the code
  • Pay attention to the permissions of the mount directory. Otherwise, the container will be shut down after a few seconds. For example: Under/data/run/mysql without permission will appear that situation just now docker run – name mysql57 – d – p 3306:3306 – v/data/mysql: / var/lib/mysql – v / data/logs/mysql/var/log/data/run/mysql/mysql – v: / var/run/mysqld – e MYSQL_ROOT_PASSWORD = 123456 – it centos/mysql: v5.7

  • Note that the directory in php.ini must be mounted to the directory configured for mysql to obtain the file content; otherwise, PHP fails to connect to mysql

      ```
      # php.ini
      mysql.default_socket = /data/run/mysql/mysqld.sock
      mysqli.default_socket = /data/run/mysql/mysqld.sock
      pdo_mysql.default_socket = /data/run/mysql/mysqld.sock
      
      # mysqld.cnf
      pid-file       = /var/run/mysqld/mysqld.pid
      socket         = /var/run/mysqld/mysqld.sock
      
      ```
    Copy the code
  • Redis cannot be connected using PHP

    # error
    $redis = new Redis;
    $rs = $redis->connect('127.0.0.1', 6379);
    
    Copy the code

    PHP failed to connect. View error log

    PHP Fatal error:  Uncaught RedisException: Redis server went away in /www/index.php:7
    Copy the code

    Considering that docker communication should not be able to use 127.0.0.1 instead of using the IP inside the container, check the IP of the Redis container

    [root@localhost docker]# docker ps
    CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS                                      NAMES
    b5f7dcecff4c        docker_nginx                         "/usr/sbin/nginx -..."4 seconds ago Up 3 seconds 0.0.0.0:80->80/ TCP, 0.0.0.0:443->443/ TCP nginx 60fd2df36d0e docker_php"/usr/local/php/sb..."   7 seconds ago       Up 5 seconds        9000/tcp                                   php
    7c7df6f8eb91        hub.c.163.com/library/mysql:latest   "docker-entrypoint..."   12 seconds ago      Up 11 seconds       3306/tcp                                   mysql
    a0ebd39f0f64        docker_redis                         "usr/local/redis/s..."   13 seconds ago      Up 12 seconds       6379/tcp                                   redis
    Copy the code

    Note that the connection address is the IP address of the container or the names of the container, such as redis or mysql. For example, nginx config PHP file parsing fastcgi_pass PHP :9000; For example PHP connects to Redisres = $redis->connect(‘redis’, 6379);

    Because the container IP is dynamic and changes after a restart, you can create a static IP

    Step 1: Create a custom network

    # Note: Network segment 172.172.0.0 is selected. You can specify any other idle network segmentDocker network create --subnet=172.171.0.0/16 docker-at docker run --name redis326 --net docker-at -- IP 172.171.0.20-d -p 6379:6379  -v /data:/data -it centos/redis:v3.2.6
    Copy the code

    Connect redis to configure the corresponding IP address, the connection is successful

    $redis = new Redis;
    $rs = $redis->connect('172.171.0.20', 6379);
    Copy the code

    There is also the possibility that phpredis cannot connect to Redis, and you may need to modify the redis.conf configuration slightly.

    bind127.0.0.1 is changed to:bind 0.0.0.0
    Copy the code
  • Error: Docker web service cannot be accessed from outside the docker web service IPv4 forwarding is disabled. Networking will not work.) Or the host is accessible, but the external is not

Conf or vi /usr/lib/sysctl.d/00-system.conf Add the following code: Net.ipv4. ip_forward=1 Restart the network service systemctl restart network to check whether the configuration is successful. Sysctl net.ipv4.ip_forward If the command output is"net.ipv4.ip_forward = 1"It means successCopy the code
  • If you cannot connect to MySQL8 using the latest version, the remote connection cannot be enabled because the password encryption mode of the latest version is changed.
# Change the password encryption mode
ALTER USER 'root'@The '%' IDENTIFIED WITH mysql_native_password BY '123456';
Copy the code

Common commands

  • docker startContainer name (container ID also works)
  • docker stopContainer name (container ID also works)
  • docker runWith the -d command, Docker will run the container in the background
  • docker psA running container
  • docker logs–tail 10 -tf Container name To view the container’s log file, -t is to add the timestamp, f is to track the latest log of a container without reading the entire log file
  • docker topContainer Name View the processes running inside a container
  • docker exec -dTouch /etc/new_config_file Creates an empty file using a background command
  • docker run --restart=always --name-d ubuntu /bin/sh -c “while true; do echo hello world; sleep 1; Done “Docker will automatically restart the container no matter what the exit code is. You can set –restart=on-failure:5 How many times did the container automatically restart
  • docker inspectContainer name Makes a detailed inspection of the container by adding –format='{(.state.running)}’ to get the specified information
  • docker rmContainer ID Delete container. Note running containers cannot be deleted
  • docker rm $(docker ps -aq)Delete all containers
  • docker rmi $(docker images -aq)Deleting all Mirrors
  • docker imagesList the mirror
  • docker pullMirror name: Label Pull mirror
  • docker searchFind publicly available images on the Docker Hub
  • docker build -t='AT/web_server:v1'You can add the Dockerfile file in the github repository directory. The command is used after writing the Dockerfile. The -t option sets the repository and name: label for the new image
  • docker loginDocker Hub login, personal authentication information will be saved to $HOME/.dockercfg,
  • docker commit -m="comment " --author="AT"Container ID Image username/repository name: tag this method is not recommended, dockerfile is recommended
  • docker historyMirror ID Delves into how images are constructed
  • docker portMirroring ID Port View the ID and port number of the container to which the mapping is to be performed. For example, query the port mapped to port 80
  • runRun a container, -p 8080:80 maps port 80 of the container to a specific port of the docker host, binds port 80 of the container to port 8080 of the host, and 127.0.0.1:80:80 binds port 80 of the container to port 80 of the host IP. -p exposes port 80 in the container to the local host
  • Docs.docker.com/reference/b… See more commands
  • docker pushThe image name pushes the image to the Docker Hub
  • docker rmiMirror name Deletes a mirror
  • docker attachContainer ID Enters the container
  • # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  • Docker network create --subnet=172.171.0.0/16 docker-atSelect network segment 172.172.0.0
  • docker build-ip specifies the container IP address 172.171.0.10

The command to delete all containers and images

docker rm `docker ps -a |awk '{print $1}'| grep [0-9 a-z] stop ` delete container docker rmi $(docker images | awk'/^<none>/ { print $3 }')
Copy the code

Dockerfile grammar

  • MAINTAINERIdentify the author and contact information of the image
  • EXPOSEMultiple EXPOSE can be specified to EXPOSE multiple ports externally, which can help connect multiple containers
  • FROMThe command specifies an existing mirror
  • \ #The symbol stands for comment
  • RUNThe command is executed using the command wrapper /bin/sh -c in the shell. If you are running on a platform that does not support shells or do not want to RUN in a shell, you can also use the exec format RUN directive
  • ENV REFRESHED_ATThe environment variable is also used to indicate when the image template was last updated
  • VOLUMEThe container adds volumes. A VOLUME is a specific directory that can be stored in one or more containers. Modification of a VOLUME takes effect immediately and does not affect image product update. For example, VOLUME[“/opt/project”,”/data”]
  • ADDCopy files and directories from the build environment to the image. Conf /conf/nginx.conf can also be a url file. If it is a compressed package, the ADD command automatically decompresses it.
  • USERSpecifies that the image will be run using that USER
  • COPYFor example, COPY conf.d/ etc/ apache2/Copies files in the local conf.d directory to the /etc/apache2/directory

Docker-compose. Yml syntax description

  • imageSpecifies the image name or image ID. If the image does not exist, Compose will attempt to pull the image from the Internet
  • buildSpecifies the path to the folder where Dockerfile resides. Compose will use it to automatically build the image and then use it
  • commandOverrides the commands executed by default when the container is started
  • linksLink to another SERVICE container using either the SERVICE name (which also serves as an ALIAS) or the SERVICE ALIAS (SERVICE:ALIAS)
  • external_linksThe container that links to the outside of docker-comemage. yml is not even a container managed by compose. The parameter format is similar to links
  • portsExpose port information. HOST machine port :CONTAINER format or just specify the port of the CONTAINER (the HOST machine will randomly assign ports) (note: When using the HOST:CONTAINER format to map ports, you may get incorrect results if you use CONTAINER ports less than 60 because YAML will parse xx: YY in base 60. Therefore, string format is recommended.
  • exposeExpose ports. Unlike Posts, Expose only exposes ports, not maps to hosts, and is only used for external service connections. Only the internal port can be specified
  • volumesExample Set the directory for attaching the volume. You can set the host path to be the container path (host:container) or add the access mode (host:container:ro)
  • volunes_fromMount all data volumes for another service or container
  • environmentSet environment variables. It can be an array or a dictionary. Given only the name of a variable, its value on the Compose host will be automatically loaded, which can be used to prevent unnecessary data leakage
  • env_fileGets environment variables from a file, either as a separate file path or as a list. If a template FILE is specified via docker-comement-f FILE, the path in env_file is based on the template FILE path. If a variable name conflicts with the environment directive, the latter prevails (every line in the environment variable file must be commented, supporting comment lines starting with #).
  • extendsExtend services based on existing services. For example, we already have a WebApp service with a template file common.yml. Write a new development.yml file and extend it with the WebApp services in common.yml. The latter automatically inherits the WebApp service in common.yml and its associated environment variables
  • netSet the network mode. Use the same value as the –net parameter of the Docker client
  • pidContainers that share the process namespace with the host system can access and manipulate each other using their process IDS
  • dnsConfigure the DNS server. It can be a value or it can be a list
  • Cap_add, cap_dropAdd or Drop Linux Capabilities for containers
  • dns_searchConfigure the DNS search domain. It can be a value or it can be a list
  • Note: docker-compose. Yml file needs to be written when docker-compose is used for composing management of Docker container. When writing docker-compose for the first time, it is easy to encounter some low-level problems, resulting in the error of yML file parsing when docker-compose up is executed. More common are yML’s strict requirements for indentation. Yml file is indent after the line, does not allow the use of TAB key characters, can only use Spaces, and the number of Spaces is also required, generally two Spaces.

Project source address :GitHub