利用 Dockfile、Docker Compose 建立 LAMP 環境 (PHP、Apache、MySQL) === 範例原始碼放在 GitHub Repo:[titangene/docker-lamp](https://github.com/titangene/docker-lamp) ## 常用 Docker 指令  圖片來源:[Gitbook - 《Docker —— 從入門到實踐》正體中文版 by Philipzheng](https://philipzheng.gitbooks.io/docker_practice/content/appendix_command/) ## 使用基本 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](https://hub.docker.com/_/php/) tag 的 image ```shell $ docker run --name my-php-apache -d -p 8000:80 php:7.1-apache 08e5975c8a279087db637782181f458cad2a10d5086454b418301de387c1ceb8 ``` ### 確定 container 是否成功執行 使用 `docker ps` 指令來確定 container 是否成功執行 (查看正在執行的 container 狀態) ```shell $ 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` 指令 ```shell $ 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.php` 或 `index.html`:  ### 進入 container 新增 `index.html` 所以接著要使用 `docker exec` 指令進入 container 來新增 `index.php` (在外部向執行中的 container 內部下指令,此時會呼叫 Container 內部的 shell 程式來執行你下的指令) 成功進入 container 後可以看到預設工作目錄就是 `/var/www/html`,這是因為官方在 image 上已經設定好了 (在 `Dockerfile` 中設定的 `WORKDIR /var/www/html`,詳情請參考官方提供的 [`Dockerfile`](https://github.com/docker-library/php/blob/master/7.1/jessie/apache/Dockerfile) ) ```shell $ docker exec -it my-php-apache bash root@08e5975c8a27:/var/www/html# ``` 接著就在 Apache web server 的根目錄 `/var/www/html` 下新增 `index.php` ```shell $ echo "<?php phpinfo(); ?>" > index.php $ cat index.php <?php phpinfo(); ?> ``` 接著輸入 `exit` 指令離開 container ```shell $ exit ``` ### 重新查看服務頁面是否正確顯示 然後開啟瀏覽器並輸入網址 `[ip-address]:8000` 就可以看到 `phpinfo()` 的畫面  ### 刪除 container 如果要刪除 container 可以使用以下指令: ```shell $ docker stop my-php-apache $ docker rm my-php-apache ``` 或是直接使用 `docker rm -f` 強制刪除正在執行的 container ```shell $ docker rm -f my-php-apache ``` ## 建立自己的 Docker Images,並 push 至 Docker Hub ### Commit images | 簡寫,名稱 | 預設 | 說明 | | ----------------- | ----- | ---------------- | | `-a`,`--author` | false | 作者 | | `-m`,`--message` | false | 提交訊息 | | `-p`,`--pause` | true | 提交期間暫停執行容器 | ```shell $ docker commit -a "titangene <titangene.tw@gmail.com>" -m "Add index.php" my-php-apache titangene/php-apache:v1.0 ``` ### 登入 Docker Hub ```shell $ 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 ```shell $ 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 ```shell $ docker run --name my-php-apache -d -p 8000:80 titangene/php-apache:v1.0 ``` ## 使用 Dockerfile 建立 PHP + Apache 環境 > 詳情請參考我另外整理的 [Dockerfile 學習筆記 by Titangene](/PnuGE_LtQhSArxhx8Ga3FA) 筆記。 ### 什麼是 Dockerfile? `Dockerfile` 是一個文字檔,其中包含了使用者可以在指令列 (command line) 上使用的所有指令,Docker 透過 `docker build` 指令執行 `Dockerfile` 中的所有指令來自動建置新的 image。 ### Dockerfile 能做什麼? - 可將環境進行版本控制 - 自動建置環境,減少重複步驟 - 自訂建立 image 時要做什麼 - 自訂建立 container 時要做什麼 ### 建立目錄 ```shell project ├── Dockerfile └── src └── index.php ``` ```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 ```dockerfile 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 的絕對路徑 ```shell $ 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 ```shell $ 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 ```shell $ docker run --name my-php-apache -d -p 8000:80 my-php ``` ### 確定 container 是否成功執行 使用 `docker ps` 指令來確定 container 是否成功執行 (查看正在執行的 container 狀態) ```shell $ 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` 目錄 ```shell $ cd project/src $ docker run -d -p 8000:80 -v `pwd`:/var/www/html php:7.1-apache ``` ### 修改 `index.php` ```shell $ vi index.html ``` ```php <?php echo '<h1>Hello World</h1>'; phpinfo(); ?> ``` 修改後可以看到 `phpinfo` 前面已出現剛剛加入的 `Hello World` 字串:  ## 利用 Docker Compose 建立 LAMP  > 詳情請參考我另外整理的 [Docker Compose 學習筆記 by Titangene](https://hackmd.io/c/H1WITKNUz/%2FBkPoXLJ4M) 筆記。 ### 什麼是 Docker Compose? - 快速建立多個 container 的工具 - 利用 `docker-compose.yml` YAML 檔來管理多個 Docker container - 並使用 `docker-compose` 指令來啟動、停止和重啟應用,以及應用中的服務和所有依賴服務的 container ### 使用的 Image - [PHP 7.1 on Apache (httpd)](https://hub.docker.com/r/_/php/) - [MySQL 5.7](https://hub.docker.com/_/mysql/) - [phpMyAdmin](https://hub.docker.com/r/phpmyadmin/phpmyadmin/) ### 建立目錄 ```shell 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`:設定環境變數 ```yaml 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`:背景執行 ```shell $ 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 的資料:  ### 停止執行、刪除服務 ```shell $ 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) ```shell $ 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 秒 ```shell $ 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](https://titangene.github.io/article/networking-in-docker-compose.html) 筆記。
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.