編寫Dockerfile
最近在部署項目事,想做一個基於ubuntu20.04,搭建nginx + php8.*的鏡像。但是在製作的過程中遇到了很多坑,記錄下來供後續參考學習。
修改鏡像過程大概分為了6個模塊:
- 模塊一:對ubuntu 20.04官方鏡像重新構造。
- 模塊二:在基礎鏡像添加php8.*的源
- 模塊三:安裝nginx、php以及相關依賴。
- 模塊四:設置nginx、php配置文件
- 模塊五:編寫nginx、php-fpm8.*啓動腳本文件
- 模塊六:鏡像打包與驗證。
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文件。
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的鏡像,説明自定義鏡像文件已經生成。
使用yangfanubuntu:v1.4鏡像創建容器
-p 指定端口號
-d 允許容器後台運行
--name 設置鏡像名字
docker run -it -d -p 8088:80 --name=laravel-crm yangfanubuntu:v1.4
使用docker ps -a 查看是否生成laravel-crm容器
驗證nginx + php8.*是否成功。