Docker+Jenkins build a multi version php environment

Keywords: Programming PHP Docker Nginx jenkins

In recent days, we have just set up a small project server, which uses the combination of docker + (jenkins, nginx, PHP FPM, mysql, redis). Let's summarize today.

Docker has been out for a long time. Even the k8s high-end gadget is very "popular". To be honest, this is the first time I use docker in a production environment.

Using docker container, you can realize "true multi version php". Multi version php is suitable for the situation that there are old projects and new projects on a server at the same time, and you can even run different parts of a project with different versions... ​

 

Host: Ubuntu 16.0.4

For a host with only one host, if it's a small project, it's a small project, and we can't cheat people (what's the main cluster and what's the node, it's too high-end for us).

 

To install docker:

Not much. Look at this: https://www.runoob.com/docker/ubuntu-docker-install.html

To install nginx:

docker run -d --name nginx \

-v /var/www:/var/www \  #Map the site directory, as well as the configuration files and logs

-p 80:80 \    #Mapping ports

nginx

 

To install php:

Here are two dockerfiles of PHP FPM, including common extensions

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y \

        libfreetype6-dev libjpeg62-turbo-dev libpng-dev \

        curl libcurl4-openssl-dev

RUN docker-php-ext-configure gd --with-freetype --with-jpeg \

    && docker-php-ext-install -j$(nproc) gd

RUN pecl install redis && docker-php-ext-enable redis

RUN docker-php-ext-install bcmath pdo pdo_mysql mysqli curl
FROM php:7.3-fpm

RUN apt-get update && apt-get install -y \

        libfreetype6-dev libjpeg62-turbo-dev libpng-dev \

        curl libcurl4-openssl-dev

RUN docker-php-ext-configure gd \

--with-png-dir \

--with-jpeg-dir \

--with-freetype-dir \

&& docker-php-ext-install -j$(nproc) gd

RUN pecl install redis && docker-php-ext-enable redis

RUN docker-php-ext-install bcmath pdo pdo_mysql mysqli curl #The extensions contained in the php source package can be installed directly with the command of docker php ext install, which is quite convenient. (however, this does not solve the dependency problem. If the extension depends on other system components, it needs to be installed separately.)

 

Create image through Dockerfile

docker build -t \

dubox/php-fpm7.4 \ #Namespace / name of the image

.     #Directory of Dockerfile

Create PHP container from dubox/php-fpm7.4

docker run -d --name php-fpm74 -v /var/www:/var/www dubox/php-fpm7.4

#Because you do not need to access PHP from the host, you do not need to map 9000 ports; mysql and Redis are the same;

 

Install mysql

docker run --name mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7

#It depends on whether 3306 port is mapped or not

 

Install Redis

docker run --name redis -d redis

 

Install Jenkins

docker run \

  -u root \

  -d \

  -p 8080:8080 \

  -p 50000:50000 \

  -v /var/jenkins-data:/var/jenkins_home \

  -v /var/run/docker.sock:/var/run/docker.sock \ #This is very important. It allows you to operate other containers like the host in Jenkins' container

  jenkinsci/blueocean

Visit http://ip:8080 to initialize jenkins and select the required plug-ins. More details can be found in: https://jenkins.io/zh/doc/book/installing/

 

Network access between containers

The nginx container needs to access the php container, and the php container needs to access mysql and redis. The network interconnection between containers can be achieved through:

1. Use container ip / / restarting the container ip may change, which is not reliable

2. Use the -- link parameter to specify the alias of the container / / there's no way for the newly added container. It's not reliable

3. Create a bridge network:

# My bridge is the name of the network, which can be customized

docker network create -d bridge my-bridge


#Connect the container to the network

docker network connect my-bridage nginx

docker network connect my-bridage php-fpm74


#View network connections

docker network inspect my-bridage

In this way, containers can be accessed through their names. For example, in nginx containers, you can ping PHP fpm74 directly

 

Containers can also access each other. It's time to configure jenkins build task

Configure jenkins build task

Create a freestyle task

Click Add to add github access private key

 

The function of checking out subdirectories is also useful, and supports jenkins environment variables (environment variable description: http://ip:8080/env-vars.html/ )In this way, the code pulled from github will be placed in a location similar to / var / Jenkins? Home / workspace / job name / job name-123.

 

Build script description:

BuildFolder=$JOB_NAME-$BUILD_NUMBER

Home="job-name"

cd $BuildFolder

rm -rf .git .gitignore

chown -R root:33 .    #Modify the home user and array of the project file, 33 is the gid of WWW data user group

chmod -R 750 .

chmod -R 770 runtime

cd ..

ln -sf /var/www/jenkinsBuild/$BuildFolder $Home   #Create soft chain, even if there is no / var/www/jenkinsBuild/$BuildFolder directory soft chain in jenkins container, it can be created successfully;

docker cp -a ./$BuildFolder nginx:/var/www/jenkinsBuild/   #Copy the project folder to the corresponding directory in the nginx container, because the php container also maps the / var/www directory, so the php container can also access it; the - a parameter here is very important, it can copy the file's owner and owner group (uid:gid) information together;

docker cp -a $Home nginx:/var/www/   #Copy soft chain

docker restart php-fpm74

docker exec -w /var/www/$Home/ php-fpm74 sh Start.sh   #You can execute some commands in the target container. The - w parameter specifies the working directory of the command

Here we need to talk about the file permissions of the docker mapping directory:

Multiple containers can map to the same host directory. The permission of the file is subject to the uid:gid carried by the file, for example:

/The main owner of var/www/index.html in php container is www data group and WWW data. The corresponding uid and gid are 33. Then, there are three situations:

1. If www data: www data and uid:gid are also 33:33 in the host or nginx container, the owner and group of the file are also www data here;

2. There is no www data in the host or nginx container, but the uid of a user named someone is 33, so the owner of this file is someone;

3. If uid and gid 33 do not exist in the host or nginx container, the file does not belong to the user. When using ls-l to view, uid and gid will be displayed directly;

Therefore, we should pay attention to the users and user groups running nginx and php FPM in the nginx and php containers. Their user names and group names can be different, but they must have the same uid or gid, otherwise there will be file access problems; if you run multiple versions of php at the same time, it is the same;

The jenkins container is run by the root user and only serves as a "Porter". Therefore, it is not important whether there are users, user groups www data and uid:gid 33 in the jenkins container, as long as you specify the uid:gid you need when modifying the file ownership

Several possible commands are provided:

useradd [username]    #New user

groupadd [groupname]   #New user group

usermod -G [groupname] [username]   #Add users to user groups

usermod -u NEW-UID username  #Modifying a user's uid

groupmod -g NEW-GID groupname  #Modify the gid of the user group

 

Finally, sell your public account

Posted by satyricon on Mon, 16 Dec 2019 23:01:24 -0800