博客 / 詳情

返回

使用Dockerfile搭建ubuntu20.04 + php8.2鏡像

編寫Dockerfile

最近在部署項目事,想做一個基於ubuntu20.04,搭建nginx + php8.*的鏡像。但是在製作的過程中遇到了很多坑,記錄下來供後續參考學習。

修改鏡像過程大概分為了6個模塊:

  1. 模塊一:對ubuntu 20.04官方鏡像重新構造。
  2. 模塊二:在基礎鏡像添加php8.*的源
  3. 模塊三:安裝nginx、php以及相關依賴。
  4. 模塊四:設置nginx、php配置文件
  5. 模塊五:編寫nginx、php-fpm8.*啓動腳本文件
  6. 模塊六:鏡像打包與驗證。

1、創建Dockerfile文件,基於ubuntu20.04官方鏡像編寫。

創建項目目錄、創建Dockerfile文件。

#創建項目目錄

mkdir laravel-crm

#切換至項目目錄

cd laravel-crm

#創建Dockerfile文件

touch Dockerfile

touch nginx.conf

touch php.ini

touch phpinfo.php

對ubuntu 20.04官方鏡像重新構造,使用LABEL 參數設置了運營人員信息。使用apt-get安裝軟件時,ubuntu20.04 系統自帶的源太慢,將apt-get源修改為國內任意可用源地址,這裏以清華大學源為例。

使用sed -i 替換/etc/apt/sources.list 鏡像,替換之後使用apt-get clean,apt-get update更新ubuntu20.40最新源地址,如以下代碼所示。

# 基礎鏡像是 Ubuntu 20.04(可使用本地已存在的鏡像作為基礎)
FROM ubuntu:20.04

#鏡像維護人員
LABEL maintainer="yangfan<834551859@qq.com>"

#ubuntu apt-get原鏡像太慢了,替換國內的鏡像,這裏是以清華大學鏡像為例。
RUN sed -i s:/archive.ubuntu.com:/mirrors.tuna.tsinghua.edu.cn/ubuntu:g /etc/apt/sources.list
RUN cat /etc/apt/sources.list
RUN apt-get clean
RUN apt-get -y update

#設置服務器時區
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

2.在基礎鏡像添加php8.*的源

ubuntu 20.04本身的php版本最高時php7.4.,而要求是要安裝php8.,查閲相關安裝資料,安裝命令如下:

#命令一
apt-get install  ca-certificates apt-transport-https software-properties-common

#命令二
add-apt-repository ppa:ondrej/php

3.安裝nginx、php以及相關依賴

#安裝nginx 
RUN apt-get update \
    && apt-get install -y nginx \ 
    php8.2 php8.2-fpm php8.2-dev \
    php8.2-gd php8.2-curl php8.2-bz2 php8.2-bcmath \
    php8.2-imap php8.2-mysql php8.2-mbstring \
    php8.2-xml php8.2-zip php8.2-soap \
    php8.2-msgpack php8.2-igbinary php8.2-ldap \
    php8.2-redis php8.2-intl \
    && php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
    && apt-get -y autoremove \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*    

# nginx默認啓動用户是www-data用户 www-data組,當php-fpm8.* 運行時生成php8.*-fpm.sock有權限

RUN mkdir -p /run/php && chown www-data:www-data /run/php

nginx默認啓動用户是www-data用户 www-data組,因此需要給 /run/php文件夾授權,在php-fpm8. 運行時可以生成php8.-fpm.sock文件。

image.png

4.設置nginx、php配置文件

#將指定文件夾內容copy到容器裏面

COPY nginx.conf /etc/nginx/nginx.conf

COPY php.ini /etc/php/8.2/fpm/php.ini


#創建工作目錄文件夾
RUN mkdir -p /var/www/html
ADD start.sh /var/www/html
ADD . /var/www/html

5.編寫nginx、php-fpm8.*啓動腳本文件

Dockerfile文件中使用CMD就可以運行程序或者腳本文件,但是當一個Dockerfile出現多個CMD的時候,自上而下執行最後一個。我們期望在docker容器啓動時,分別啓動nginx、php-fpm8.*,則需要放在腳本文件裏面進行啓動。

#工作目錄 
WORKDIR /var/www/html

#對外暴露端口
EXPOSE 80
EXPOSE 443
EXPOSE 9000

#CMD 指令指定在容器啓動時執行的命令
#CMD ["sh","-c","php-fpm7.4"]

#CMD ["nginx","-g","daemon off;"]
CMD ["./start.sh"]

根據上面5個模塊,最終Dockerfile腳本文件如下。

# 基礎鏡像是 Ubuntu 20.04(可使用本地已存在的鏡像作為基礎)
FROM ubuntu:20.04

#鏡像維護人員
LABEL maintainer="yangfan<834551859@qq.com>"

#ubuntu apt-get原鏡像太慢了,替換國內的鏡像,這裏是以清華大學鏡像為例。
RUN sed -i s:/archive.ubuntu.com:/mirrors.tuna.tsinghua.edu.cn/ubuntu:g /etc/apt/sources.list
RUN cat /etc/apt/sources.list
RUN apt-get clean
RUN apt-get -y update

#設置服務器時區
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 擴展依賴
RUN apt-get install -y \
    apt-utils \
    curl \
    git \
    apt-transport-https \
    software-properties-common \
    g++ \
    build-essential 


#ubuntu 20.04 apt 安裝 PHP8.0
RUN add-apt-repository -y ppa:ondrej/php

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

#安裝nginx 
RUN apt-get update \
    && apt-get install -y nginx \ 
    php8.2 php8.2-fpm php8.2-dev \
    php8.2-gd php8.2-curl php8.2-bz2 php8.2-bcmath \
    php8.2-imap php8.2-mysql php8.2-mbstring \
    php8.2-xml php8.2-zip php8.2-soap \
    php8.2-msgpack php8.2-igbinary php8.2-ldap \
    php8.2-redis php8.2-intl \
    && php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
    && apt-get -y autoremove \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*    

# nginx默認啓動用户是www-data用户 www-data組,當php-fpm8.* 運行時生成php8.*-fpm.sock有權限

RUN mkdir -p /run/php && chown www-data:www-data /run/php


#將指定文件夾內容copy到容器裏面

COPY nginx.conf /etc/nginx/nginx.conf

COPY php.ini /etc/php/8.2/fpm/php.ini


#創建工作目錄文件夾
RUN mkdir -p /var/www/html
ADD start.sh /var/www/html
ADD . /var/www/html

RUN chmod +x /var/www/html/start.sh


#工作目錄 
WORKDIR /var/www/html

#對外暴露端口
EXPOSE 80
EXPOSE 443
EXPOSE 9000

#CMD 指令指定在容器啓動時執行的命令
#CMD ["sh","-c","php-fpm7.4"]

#CMD ["nginx","-g","daemon off;"]
CMD ["./start.sh"]

nginx.conf配置文件如下:

# 全局配置
user www-data;

worker_processes auto;

error_log /var/log/nginx/error.log warn;
 
events {
    worker_connections  1024;
}
 

# http 配置
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
 
    # 訪問日誌配置
    access_log /var/log/nginx/access.log;
 
    # 服務器塊
    server {
        listen 80;
        server_name localhost;
        #laravel配置目錄,根據自己項目需要,重新設置文件目錄;
        root /var/www/html/public;
 
        location / {
            index index.php index.html;
            try_files $uri $uri/ /index.php?$query_string;

            if (!-e $request_filename){ 
               rewrite ^/(.*) /index.php last; 
            }

        }
 
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
             root /var/www/html/public;
        }


        location ~ \.php(.*)$ {
            fastcgi_pass   unix:/run/php/php8.2-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
            include        fastcgi.conf;
        }    
    }
}

php.ini配置文件,如下:

; Execution, size, upload
 max_input_time = 60
 max_execution_time = 60
 memory_limit = 256M
 post_max_size = 56M
 upload_max_filesize = 56M
 output_buffering = 4096
 realpath_cache_size = 4096k
 realpath_cache_ttl = 600
;
; ; Error
 log_errors = On
 error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
 display_errors = Off
 display_startup_errors = Off
;
; ; Security
 allow_url_fopen = Off
 allow_url_include = Off
 disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
;
; ; Misc
 request_order = "GP"
 variables_order = "GPCS"
 register_argc_argv = Off
 short_open_tag = Off
 zend.assertions = -1
; [CLI Server]
 cli_server.color = On
; [Session]
 session.sid_bits_per_character = 5
 session.gc_divisor = 1000
 session.sid_length = 26
; [mysqlnd]
 mysqlnd.collect_statistics = Off
 mysqlnd.collect_memory_statistics = Off
; [opcache]
 opcache.enable=1
 opcache.memory_consumption=512
 opcache.interned_strings_buffer=64
 opcache.max_accelerated_files=32531
 opcache.validate_timestamps=0
 opcache.save_comments=1
 opcache.fast_shutdown=1

start.sh腳本如下:

#!/bin/bash

echo "------------nginx start-----"

cd /usr/sbin

pwd

policy-rc.d

php-fpm8.2 -D

nginx -g "daemon off;"

ps aux | grep nginx

ps aux | grep php-fpm
echo "------------nginx end -----"

phpinfo.php文件內容如下:

<?php
   phpinfo();
?>

6.鏡像打包與驗證。

在laravel-crm文件夾執行鏡像打包命令,並驗證鏡像文件是否已生成。

docker build -t "yangfanubuntu:v1.4" .

使用 docker images 查看本機所有鏡像,確實有一個名字叫yangfanubuntu:v1.4的鏡像,説明自定義鏡像文件已經生成。
image.png

使用yangfanubuntu:v1.4鏡像創建容器
-p 指定端口號
-d 允許容器後台運行
--name 設置鏡像名字

docker run -it -d -p 8088:80 --name=laravel-crm yangfanubuntu:v1.4

image.png

使用docker ps -a 查看是否生成laravel-crm容器

image.png

驗證nginx + php8.*是否成功。
image.png

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.