2021年1月4日 星期一

利用 Dockfile、Docker Compose 建立 LAMP 環境 (PHP、Apache、MySQL)

常用 Docker 指令

圖片來源:Gitbook - 《Docker —— 從入門到實踐­》正體中文版 by Philipzheng

 

使用基本 Docker 指令建立 PHP + Apache 環境

建立並執行 container

接著使用 docker run 指令來建立並執行 container,下面是參數說明:

  • --name my-php-apache:設定 container 名稱為 my-php-apache
  • -d:container 在背景執行
  • -p 8000:80:指定一個 port,host 對外開 8000 port,container 對內開 80 port
  • php:7.1-apache:使用 PHP 官方在 Docker Hub 上提供的 7.1-apache tag 的 image
$ docker run --name my-php-apache -d -p 8000:80 php:7.1-apache
08e5975c8a279087db637782181f458cad2a10d5086454b418301de387c1ceb8

確定 container 是否成功執行

使用 docker ps 指令來確定 container 是否成功執行 (查看正在執行的 container 狀態)

$ docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS          PORTS                  NAMES
08e5975c8a27   php:7.1-apache   "docker-php-entryp..."   11 seconds ago   Up 10 seconds   0.0.0.0:8000->80/tcp   my-php-apache

查詢主機的 IP 位址

接著是查詢主機的 IP 位址,如果是 Linux 或 masOS 可使用 ifconfig 指令,如果是 Windows 則是使用 ipconfig 指令

$ ifconfig
...
ens33   Link encap:Ethernet  HWaddr 00:0c:29:89:a0:57
        inet addr:192.168.191.130  Bcast:192.168.191.255  Mask:255.255.255.0
        inet6 addr: fe38::ec00:21cf:ce7f:1e8d/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:131354 errors:0 dropped:0 overruns:0 frame:0
        TX packets:19549 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000
        RX bytes:190319852 (190.3 MB)  TX bytes:1769853 (1.7 MB)
...

查看服務頁面顯示 403 錯誤

開啟瀏覽器並輸入網址 [ip-address]:8000 (Port 是剛剛建立 container 時設定的),會發現出現 403 錯誤,原因是因為我們還沒在 Apache web server 的根目錄 /var/www/html 下放首頁 index.phpindex.html

進入 container 新增 index.html

所以接著要使用 docker exec 指令進入 container 來新增 index.php (在外部向執行中的 container 內部下指令,此時會呼叫 Container 內部的 shell 程式來執行你下的指令)

成功進入 container 後可以看到預設工作目錄就是 /var/www/html,這是因為官方在 image 上已經設定好了 (在 Dockerfile 中設定的 WORKDIR /var/www/html,詳情請參考官方提供的 Dockerfile )

$ docker exec -it my-php-apache bash
root@08e5975c8a27:/var/www/html#

接著就在 Apache web server 的根目錄 /var/www/html 下新增 index.php

$ echo "<?php phpinfo(); ?>" > index.php
$ cat index.php
<?php phpinfo(); ?>

接著輸入 exit 指令離開 container

$ exit

刪除 container

如果要刪除 container 可以使用以下指令:

$ docker stop my-php-apache
$ docker rm my-php-apache

或是直接使用 docker rm -f 強制刪除正在執行的 container

$ docker rm -f my-php-apache

重新查看服務頁面是否正確顯示

然後開啟瀏覽器並輸入網址 [ip-address]:8000 就可以看到 phpinfo() 的畫面

建立自己的 Docker Images,並 push 至 Docker Hub

Commit images

簡寫,名稱 預設 說明
-a--author false 作者
-m--message false 提交訊息
-p--pause true 提交期間暫停執行容器
$ docker commit -a "titangene <titangene.tw@gmail.com>" -m "Add index.php" my-php-apache titangene/php-apache:v1.0

登入 Docker Hub

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username (titangene):
Password:
Login Succeeded

push image 至 Docker Hub

$ docker push [image]
$ docker push titangene/php-apache:v1.0
The push refers to a repository [docker.io/titangene/php-apache]
b0a5a0170d8f: Pushed
d7ca93da4280: Pushed
3be05f838c62: Pushed
...
v1.0: digest: sha256:ea3454... size: 3242

使用之前儲存的 image

$ docker run --name my-php-apache -d -p 8000:80 titangene/php-apache:v1.0

使用 Dockerfile 建立 PHP + Apache 環境

詳情請參考我另外整理的 Dockerfile 學習筆記 by Titangene 筆記。

什麼是 Dockerfile?

Dockerfile 是一個文字檔,其中包含了使用者可以在指令列 (command line) 上使用的所有指令,Docker 透過 docker build 指令執行 Dockerfile 中的所有指令來自動建置新的 image。

Dockerfile 能做什麼?

  • 可將環境進行版本控制
  • 自動建置環境,減少重複步驟
  • 自訂建立 image 時要做什麼
  • 自訂建立 container 時要做什麼

建立目錄

project
├── Dockerfile
└── src
    └── index.php
// src/index.php
<?php
echo '<h1>Hello World</h1>';
phpinfo();
?>

Dockerfile

  • FROM php:7.1-apache:第一條命令必須為 FROM,說明使用哪個 image 作為基底 (Base Image)
  • COPY src /var/www/html/:將 Dockerfile 所在目錄的 src 資料夾內的資料複製到 container 內的 /var/www/html/
  • EXPOSE 80:開放 80 port
FROM php:7.1-apache
COPY src /var/www/html/
EXPOSE 80

利用 Dockerfile 建立 Docker Image

  • -t:添加標記 (tag)
    • 指定此 image 的名稱 (name) 和標記 (tag)
    • 格式:docker build -t name:tag .
    • tag 可用來區分同一個 repository 的不同 image (通常作為版本號)
    • EX:Ubuntu repo 中有多個 image,通過 Tag 來區分發行版本,例如 12.04、13.04、14.04 … 等
  • . (一點):指定 Dockerfile 所在的路徑
    • 這邊的 . 點指的是當前目錄,也可以換成 Dockerfile 的絕對路徑
$ cd project
$ ls
Dockerfile  src/

$ docker build -t my-php .
Sending build context to Docker daemon  3.584kB
Step 1/3 : FROM php:7.1-apache
 ---> b7ce92f2bd78
Step 2/3 : COPY src /var/www/html/
 ---> 3b6ac8f06072
Step 3/3 : EXPOSE 80
 ---> Running in 0f36c2370aff
Removing intermediate container 0f36c2370aff
 ---> 365eace4a8d4
Successfully built 365eace4a8d4
Successfully tagged my-php:latest

查看目前 image

查看 local 有哪些 image,確定是否有名為 my-php 的 Docker Image

$ docker images
REPOSITORY   TAG          IMAGE ID       CREATED          SIZE
my-php       latest       365eace4a8d4   18 seconds ago   392MB
php          7.1-apache   b7ce92f2bd78   2 days ago       392MB

使用自建的 image 來新建並啟動 container

$ docker run --name my-php-apache -d -p 8000:80 my-php

確定 container 是否成功執行

使用 docker ps 指令來確定 container 是否成功執行 (查看正在執行的 container 狀態)

$ docker ps
CONTAINER ID   IMAGE    COMMAND                  CREATED          STATUS          PORTS                  NAMES
dc194e799ca7   my-php   "docker-php-entrypoi…"   49 seconds ago   Up 46 seconds   0.0.0.0:8000->80/tcp   quirky_booth

Docker Volume

在上一個範例,為了要把 index.php 首頁檔放入 Apache web server 的根目錄 /var/www/html 下,要先利用 docker exec 指令進去 container 裡面操作,但是這樣非常麻煩,有沒有方便的方法?

那就要提到 Docker Volume 的概念:掛載主機上的指定目錄到 container 的指定目錄上 (將主機上的目前目錄 bind 到 container 的指定目錄)。

  • -v `pwd`:/var/www/html:將 Host 端的目前目錄 ( pwd ) 掛載到 container 的 /var/www/html 目錄
$ cd project/src
$ docker run -d -p 8000:80 -v `pwd`:/var/www/html php:7.1-apache

修改 index.php

$ vi index.html
<?php
echo '<h1>Hello World</h1>';
phpinfo();
?>

修改後可以看到 phpinfo 前面已出現剛剛加入的 Hello World 字串:

利用 Docker Compose 建立 LAMP

詳情請參考我另外整理的 Docker Compose 學習筆記 by Titangene 筆記。

什麼是 Docker Compose?

  • 快速建立多個 container 的工具
  • 利用 docker-compose.yml YAML 檔來管理多個 Docker container
  • 並使用 docker-compose 指令來啟動、停止和重啟應用,以及應用中的服務和所有依賴服務的 container

使用的 Image

建立目錄

project
├── docker-compose.yml
├── mysql
│   ├── Dockerfile
│   └── sql
│       └── testdb.sql
├── php
│   └── Dockerfile
└── www
    ├── db.php
    └── index.php

docker-compose.yml

  • build:指定要使用的 Dockerfile 所在目錄,Docker Compose 會自動幫你執行 docker build 指令的動作
  • image:直接使用某 Docker image 來建立該 container
  • ports: [hostPort]:[ContainerPort]:設定 port mapping,指定一個 port,host 對外開 [hostPort] port,container 對內開 [ContainerPort] port
  • depends_on:依據依賴順序啟動服務
  • volumes: [hostPath]:[containerPath]:掛載主機上的指定 [hostPath] 目錄到 container 的指定目錄 [containerPath]
  • environment:設定環境變數
version: '3.3'

services:
  phpapache:
    #image: titangene/php-apache-mysql:v1.0
    build: ./php
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - mysql
    volumes:
      - ./www:/var/www/html
  mysql:
    build: ./mysql
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: admin
      #MYSQL_DATABASE: testdb
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "8080:80"
    depends_on:
      - mysql
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306

利用 Docker Compose 啟動服務

  • -d:背景執行
$ docker-compose up -d
Creating dockerlamp_mysql_1      ... done
Creating dockerlamp_phpmyadmin_1 ... done
Creating dockerlamp_phpapache_1  ... done

用瀏覽器開啟 localhost 就會看到 index.php 的頁面:

接著開啟 localhost:8080 登入 phpMyAdmin:

接著開啟 localhost/db.php 可看到 PHP 能正確讀取到 MySQL 的資料:

停止執行、刪除服務

$ docker-compose stop
Stopping dockerlamp_phpmyadmin_1 ... done
Stopping dockerlamp_phpapache_1  ... done
Stopping dockerlamp_mysql_1      ... done

$ docker-compose rm
Going to remove dockerlamp_phpmyadmin_1, dockerlamp_phpapache_1, dockerlamp_mysql_1
Are you sure? [yN] y
Removing dockerlamp_phpmyadmin_1 ... done
Removing dockerlamp_phpapache_1  ... done
Removing dockerlamp_mysql_1      ... done
  • -s:會先讓 container 停止執行,然後再刪除 container
  • -f:會自動確認刪除 container (原本會問 Y or N)
$ docker-compose rm -sf
Stopping dockerlamp_phpmyadmin_1 ... done
Stopping dockerlamp_phpapache_1  ... done
Stopping dockerlamp_mysql_1      ... done
Going to remove dockerlamp_phpmyadmin_1, dockerlamp_phpapache_1, dockerlamp_mysql_1
Removing dockerlamp_phpmyadmin_1 ... done
Removing dockerlamp_phpapache_1  ... done
Removing dockerlamp_mysql_1      ... done

停止容器並移除由 up 建立的容器、網絡、volume、image

docker-compose down 指令預設只刪除以下內容:

  • 在 Compose 檔案中,定義的服務容器
  • 在 Compose 檔案中,定義在 networks 欄位的網絡
  • 預設網絡 (如果有使用的話)

在 Compose 檔案中,定義在 external 欄位的網絡和 volume 不會被刪除

  • --rmi type:刪除 image,type 必須從下面選一個:
    • all:刪除任何服務使用的所有 image
    • local:只刪除沒有在 image 欄位設定的自定標籤 image
  • -v--volumes:刪除 Compose 檔案 volumes 欄位上有命名的 volume 和 attach 到 container 的匿名 volume
  • --remove-orphans:刪除未在 Compose 檔案中定義的服務容器
  • -t--timeout TIMEOUT:指定 shutdown timeout,以秒為單位,預設為 10 秒
$ docker-compose down --rmi local
Stopping dockerlamp_phpmyadmin_phpapache_1  ... done
Stopping dockerlamp_phpmyadmin_phpmyadmin_1 ... done
Stopping dockerlamp_phpmyadmin_mysql_1      ... done
Removing dockerlamp_phpmyadmin_phpapache_1  ... done
Removing dockerlamp_phpmyadmin_phpmyadmin_1 ... done
Removing dockerlamp_phpmyadmin_mysql_1      ... done
Removing network dockerlamp_phpmyadmin_default
Removing image dockerlamp_phpmyadmin_mysql

透過 Docker Compose 設定 network

詳情請參考我另外整理的 透過 Docker Compose 設定 network by Titangene 筆記。

 

 Dockerfile in php dir

FROM php:5.3-apache
EXPOSE 80

Dockerfile in mysql dir

FROM mysql
EXPOSE 3306

 docker-compose.yml

version: '2'

services:
  phpserver:
    image: php:5.3-apache
    build: ./php
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./www:/var/www/html
  mysql:
    image: mysql
    build: ./mysql
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: admin
      #MYSQL_DATABASE: testdb
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "8080:80"
    depends_on:
      - mysql
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306

沒有留言: