本期目標 : 基於 Centos 7.6 , 封裝出一個可用於運行 php 項目的開箱即用鏡像
本文不討論 dockerfile 語法 , 而且假設你懂得基本的類unix 操做系統常識並擁有類unix 運行環境 (包括但不限於安裝了mac 或 linux 的實體機 , 類unix虛擬機 , 安裝了 MinGW 或 CygWin 的 windows 機器) , 而且認爲你懂得基本的 docker 操做和有必定的 dockerfile 閱讀能力
創建工做目錄php
mkdir ~/docker-learn cd ~/docker-learn
建立Dockerfilehtml
touch Dockerfile
而後拷貝你經常使用的 nginx.conf 到工做目錄mysql
cp xxx/nginx.conf nginx.conf
編輯咱們建立好的 Dockerfilelinux
聲明本鏡像繼承自 centos 最新版nginx
FROM centos
建立nginx源文件sql
因爲 centos 倉庫裏是沒有 nginx 的 , 因此咱們要自力更新添加nginx的源到 docker 裏
複製 nginx.org 裏關於 RHEL 源的內容到 nginx.repo 文件
也能夠本地執行如下命令建立 nginx.repodocker
sudo tee ./nginx.repo <<-'EOF' [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key EOF
寫入複製 nginx.repo 指令到docker鏡像中apache
COPY nginx.repo /etc/yum.repos.d/nginx.repo
使用yum安裝nginx並設置爲開機啓動windows
RUN yum makecache && yum install nginx && chkconfig nginx on
centos 默認源中擁有低版本的 php 以及相關包 , 咱們須要換一個版本新一些的源 .
本文 remi開源鏡像
安裝 remi 源centos
RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm && yum update -y
使用 yum 安裝php和相關包並設置爲開機啓動
RUN yum install -y --enablerepo=remi --enablerepo=remi-php72 php php-openssl php-curl php-bcmath php-devel php-mbstring php-mcrypt php-mysqlnd php-pdo php-gd php-xml php-opcache php-fpm && chkconfig php-fpm on
衆所周知,若是要推送到線上的話鏡像越小越好,docker yum 的運行會生成大量緩存,那麼咱們就頗有必要作一些清理工做了
RUN yum clean headers && yum clean packages && yum clean metadata && rm -rf /usr/share/man
即容器運行時執行的第一個命令,若是不是 init 的話頗有可能部分特權命令沒法運行,例如 chkconfig
ENTRYPOINT ["/sbin/init"]
dockerfile 中的每一個指令都會單獨生成一層鏡像,這樣勢必會增長咱們的鏡像體積
一般作法是儘量把多條指令整理順序合併爲一條,就能夠有效減少鏡像體積
FROM centos # 複製兩個repo COPY conf/tsinghua-base.repo /etc/yum.repos.d/CentOS-Base.repo COPY conf/nginx.repo /etc/yum.repos.d/nginx.repo # 安裝組件和相關包 RUN yum makecache && yum -y install nginx && chkconfig nginx on && yum install -y epel-release && rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm && yum update -y && yum install -y --enablerepo=remi --enablerepo=remi-php72 php php-openssl php-curl php-bcmath php-devel php-mbstring php-mcrypt php-mysqlnd php-pdo php-gd php-xml php-opcache php-fpm && chkconfig php-fpm on && yum clean headers && yum clean packages && yum clean metadata && rm -rf /usr/share/man # 聲明入口點 ENTRYPOINT ["/sbin/init"]
構建鏡像
值得注意的是 nginx 官方 repo 並非很穩定 , 運行時可能會出錯 , 重試幾回通常均可以成功
若是是其餘類型的錯誤,那麼就要檢查環境以及 dockerfile 有沒有問題
docker build . -t first-build
帶有特權啓動一個後臺運行的容器,將會返回一個ID
使用了 --privileged 選項以後,容器會擁有真的 root 權限,不然就只有本地普通用戶權限.容器中執行了某些特殊操做(例如 systemctl)時才須要該選項
docker run -d --privileged first-build
測試鏡像的運行情況
docker exec -it ( docker run 命令返回的ID ) ps aux | grep '[nginx|php]'
若是返回結果相似這樣,那麼說明咱們的操做是正確的
> docker exec -it cca6 ps aux | grep '[nginx|php]' root 1 0.0 0.0 43112 4888 ? Ss 09:15 0:00 /sbin/init root 17 0.0 0.0 39096 6476 ? Ss 09:15 0:00 /usr/lib/system root 29 0.1 0.0 35100 3308 ? Ss 09:15 0:00 /usr/lib/system root 370 0.0 0.1 371588 21424 ? Ss 09:15 0:00 php-fpm: master root 381 0.0 0.0 24264 2784 ? Ss 09:15 0:00 /usr/lib/system dbus 386 0.0 0.0 58000 4164 ? Ss 09:15 0:00 /usr/bin/dbus-d root 418 0.0 0.0 46432 980 ? Ss 09:15 0:00 nginx: master p nginx 421 0.0 0.0 46832 3512 ? S 09:15 0:00 nginx: worker p root 564 0.0 0.0 8096 1820 tty1 Ss+ 09:15 0:00 /sbin/agetty -- apache 822 0.0 0.0 371588 12468 ? S 09:15 0:00 php-fpm: pool w apache 825 0.0 0.0 371588 12468 ? S 09:15 0:00 php-fpm: pool w root 2859 0.0 0.0 51752 3448 pts/0 Rs+ 09:21 0:00 ps aux
此時若是使用了端口映射來啓動鏡像,那麼你甚至能夠在本地瀏覽器裏看到 nginx 的默認歡迎頁
docker run -d --privileged -p 8080:80 first-build
進入阿里雲鏡像控制檯,
https://cr.console.aliyun.com/cn-zhangjiakou/instances/repositories
界面大概長像這樣
點開左下角的鏡像加速器https://cr.console.aliyun.com/cn-zhangjiakou/instances/mirrors,你會看到你專屬的加速連接
找到你的操做系統,逐條執行便可,本文使用 Ubuntu 版本.
可見執行很順利,沒有任何異常
sudo docker login --username=你的阿里雲用戶名 registry.cn-zhangjiakou.aliyuncs.com Password: 你的阿里雲密碼 Login Succeeded
點擊左側的命名空間,點擊建立命名空間,輸入你的命名空間名稱
命名空間能夠理解爲鏡像所屬的組織
例如: centos 鏡像的全名是 docker.io/centos,docker.io 就是centos鏡像的命名空間,可是docker.io這個命名空間下卻存在不止centos一種鏡像.公開和私有是指鏡像是否能夠在阿里雲鏡像市場中被大衆查看和是否可以不須要任何權限拉取
剛纔咱們已經建立好了命名空間,那麼接下來就是建立倉庫了.
倉庫能夠理解爲組織建立的軟件包包名
例如: centos 鏡像的全名是 docker.io/centos,centos 就是docker.io的一個倉庫(軟件),同時centos這個軟件能夠有不少個版本.
進入 https://cr.console.aliyun.com/cn-zhangjiakou/instances/repositories 倉庫頁面 , 點擊新建倉庫.
命名空間選擇剛纔建立好的,摘要即爲鏡像簡介.
點擊下一步,代碼源選擇本地倉庫
點擊建立鏡像倉庫以後,就會發現頁面上多了一行數據,說明建立成功
鼠標放到那個下載同樣的圖標上,會看到倉庫的專屬地址
咱們要把咱們剛纔構建的一個叫作 first-build 的鏡像推送到阿里雲倉庫中.首先咱們使用 docker images | grep first-build
查找到它鏡像ID.接下來咱們修改鏡像的名字爲符合docker第三方倉庫的鏡像名格式.
第三方鏡像倉庫鏡像名格式:倉庫地址/組織/鏡像名:鏡像版本號以阿里云爲例:阿里雲倉庫地址/命名空間/倉庫名:版本 registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1
而後執行如下命令來修改:
docker tag 3482e8529a90 registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1
再次使用 docker images | grep first-build
發現已經找不到了,由於它的名字已經變掉了
sudo docker push registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker
等全部的 Pushing 運行結束以後咱們會發現阿里雲倉庫中多了一個版本.
至此,鏡像已經推送成功.咱們已經能夠基於阿里雲的支持,在全世界範圍內使用咱們的鏡像.
對於向開源事業無私奉獻的阿里雲致敬
如今咱們就要研究怎麼讓鏡像跑咱們本身的項目了
此次就能夠基於咱們推送阿里雲的鏡像了
FROM registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1
複製咱們準備好的 nginx.conf 到鏡像裏
COPY nginx.conf /etc/nginx/conf/nginx.conf
nginx.conf 全文
user nginx; worker_processes auto; pid /run/nginx.pid; events { worker_connections 1024; } http { server { listen 80; server_name 127.0.0.1; root /var/www/html; index index.php; location ~ \.php($|/) { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } }
複製工程源碼到鏡像裏
在當前目錄創建咱們的工程,而且僞裝咱們的工程只有一個文件,它位於./proj
複製咱們的工程到鏡像裏併爲運行目錄加權
COPY proj /var/www/html RUN chmod -R 755 /var/www/html/
Dockerfile 全文
FROM registry.cn-zhangjiakou.aliyuncs.com/leasn-docker/learn-docker:1 COPY nginx.conf /etc/nginx/nginx.conf COPY proj /var/www/html RUN chmod -R 755 /var/www/html/
構建鏡像並使用端口映射運行咱們的容器
docker build . docker run --privileged -d -p 8080:80 773ed8872493
若是不出意外,咱們已經能夠在本地的 127.0.0.1:8080 中看到 phpinfo() 了
既然phpinfo已經看到了,那麼如何讓整個工程跑起來我就不贅述了.
值得一提的是,推送新版本到
Compose 是一個用於定義和運行多容器Docker應用程序的工具。使用Compose,您可使用YAML文件來配置應用程序的服務。而後,使用單個命令,您能夠從配置中建立並啓動全部服務該應用使用
sudo apt install docker-compose
安裝
調整目錄結構
在咱們如今工做目錄外面再加一層目錄,大體是: 工做目錄 > docker-learn (之前的工做目錄) && docker-compose.yaml
目錄樹形結構:
docker-compose 包含多個指令,並採用 yaml語言編寫.能夠理解爲把咱們在命令行運行的 run 命令參數寫到了文件裏,通過統一的工具協調啓動.
主要指令:
version 版本信息,不知道爲何必須是 3
version: 3
services 須要編排的服務列表,本次咱們主要編寫一個叫作 docker-learn 的服務
services:
version: '3' services: # 服務名 docker-learn: # 該服務是否以特權啓動 , 即 --privileged privileged: true # 構建 build: # 構建上下文 即: docker build ./docker-learn context: ./docker-learn # 端口映射,即 -p 80:80 ports: - 80:80 # 對外暴露的端口 ,至關於Dockerfile 的 EXPOSE 指令 # EXPOSE指令只是聲明瞭容器應該打開的端口,可是並無實際上將它打開! # 該選項在 docker run -it -P(大寫) 時會真的起做用 expose: - 80 # 目錄映射 , 至關於 docker run -v # volumes: # - ./logs/php-fpm:/var/log/php-fpm # - ./logs/nginx:/var/log/nginx
使用docker-compose 啓動鏡像
關閉其餘運行中的容器,以避免與咱們即將運行的容器衝突
docker ps | awk '{print $1}' | grep -v CON | xargs docker kill
啓動鏡像
單獨 up 不使用服務名會運行 services 中定義的全部容器.
若是services中有多個服務,那麼可使用 up 服務名來單獨 up 一個服務容器
up 默認會使用 build:context 中的 Dockerfile 文件編譯好的鏡像進行容器啓動,--build 是強制再次使用 Dockerfile 進行從新編譯鏡像再啓動 . 可是 --build 仍然會使用已經存在的鏡像層的緩存
--force-recreate 從新編譯時不使用鏡像層緩存 , 徹底從新編譯若是出現 bind: address already in use 相似的提示 , 就換一個 ports 裏的綁定端口重試
docker-compose up [docker-learn] [--build] [--force-recreate]
咱們發現如今訪問 127.0.0.1:8080 仍然能夠看到 phpinfo
更新中
更新中