前言
這是一份未整理過的 Docker 學習筆記
環境
GCP - ubuntu 18.04
安裝
移除舊版本
sudo apt-get remove docker docker-engine docker.io containerd runc |
安裝前設定
更新 apt
sudo apt-get update |
使 apt 可以經由 HTTPS 使用倉庫
- 安裝以下套件,使
apt
可以經由 HTTPS 使用倉庫sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
增加 Docker 的正式 GPG 密鑰
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - |
核對一下我們現在擁有含有
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
指印的密鑰,我們可以搜尋最後八碼sudo apt-key fingerprint 0EBFCD88
理應得到輸出如下:
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown] Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
設定 Docker 倉庫版本
- 將
Docker 倉庫
設定為stable
版,若要設定為nightly
或test
版,可在以下的指令中自由取代stable
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
安裝 Docker
安裝最新的
Docker CE
版本sudo apt-get install docker-ce docker-ce-cli containerd.io -y
你也可以安裝特定版本的
Docker
:
列出版本
apt-cache madison docker-ce
應該會得到輸出如下:
docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 18.06.1~ce~3-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 18.06.0~ce~3-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
...使用上面輸出的第二欄位版本號,結合下面的指令來安裝特定版本
sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
運行鏡像
hello-world
來驗證Docker CE
是否已經正確安裝sudo docker run hello-world
如果要使用非
root
身份運行Docker
的話,可以把你的使用者加到Docker
群組sudo usermod -aG docker your-user
解除安裝
解除安裝
Docker CE
sudo apt-get purge docker-ce
刪除所有的
image
,containers
,volumes
, 可以使用以下指令。慎用!此指令適合解除安裝後使用。sudo rm -rf /var/lib/docker/
docker
- 列出
Docker
的指令docker
docker version
- 查看
Docker
版本docker version
Docker info
- 查看
Docker
完美安裝資訊docker info
docker network
列出 network
docker network ls |
查看 network
docker network inspect networkName |
建立 network
docker network create -d driverType networkName |
docker volume
列出 volume 清單
docker volume ls |
列出特定 volume 訊息
docker volume inspect volumeName |
刪除 volume
docker volume rm volumeName |
清除所有未掛載的 volume
docker volume prune |
docker container exec
以 root 登入容器
docker exec -it --user root <container id> /bin/bash |
連接還在運行中的 container
docker container exec -it yourContainerIDOrContainerName bash |
exec
在運行中的 container
中運行一個新的程序
docker cp
傳檔案進 container
docker cp file containerName:/location |
確認 Docker daemon
運行狀況
service docker status |
systemctl is-active docker |
Docker container run
運行 container
docker container run -it ubuntu:latest /bin/bash |
Docker container run
告訴Docker daemon
開始一個新的container
-i
告訴Docker daeman
讓container
可以互動-t
使目前的 terminal 視窗連接container
的shell
ubuntu:latest
為開始這個container
的image
/bin/bash
指定了我們想要運行container
裡頭的哪一個程序
docker container run -d \ |
-d
表示讓 container
運行在背景 , 與 -it
相反,無法共存--name
指定 container
的名稱-p
指定 port
, 左邊的是外部可以從瀏覽器存取的 port ,右邊的是 container 向外暴露的 port
架設一個私有倉庫
docker run -d -p 5000:5000 registry |
我們也可以將上傳的映像檔備份一份到容器外
docker run -d -p 5000:5000 -v outsideAddress:insideAddress registry |
備份容器的 volume
比方說, 先建立一個容器叫做 dbstore, 並且內建一個匿名 volume, 掛在容器內的 /dbdata 位址
docker run -v /dbdata --name dbstore ubuntu /bin/bash
接下來, 備份的步驟如下:
- 建立一個新容器, 並且掛載 dbstore 上的 volume, 下面指令中的
--volumes-from
達成這一項 - 將本機的一個資料夾掛到容器中的 /backup, 下面指令中的
-v $(pwd):/backup
達成這一項 - 接下來, 我們要把從 dbstore 掛載過來的, 容器內的 /dbdata 資料夾備份到容器外, 下面指令中的
tar cvf /backup/backup.tar /dbdata
達成這一項 - 當備份完成後, 該容器內沒有其他執行的任務, 所以該容器關閉,
--rm
會讓關閉後的容器自行銷毀
- 建立一個新容器, 並且掛載 dbstore 上的 volume, 下面指令中的
docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata |
掛載一個 volume
docker run -d --name mysql2 -v mysql:/var/lib/mysql -p 3310:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.7 |
-v
: 外部建立一個 volume 叫做 mysql, 並且掛載到容器內部的 /var/lib/mysql 位置-p
: 映射內外 port-e
: 環境變數-d
: 背景執行
連接到一個指定的容器
docker run --name test2 --link test1 -d busybox /bin/sh -c "while true; do echo hello; sleep 10; done" |
指定一個 network
docker run --name test3 --network demo -d busybox /bin/bash |
--network
: 指定連接到 demo network
與該 container 共享網路
docker run --name test3 --network container:test2 -d busybox /bin/bash |
docker system
查看 Docker 真實系統佔用空間
docker system df |
離開 container
但不關掉它
CTRL + PQ |
docker container ls
列出運行中的
container
docker container ls
列出所有的
container
, 包含已停止的docker container ls -a
or
docker ps -a |
docker container stop
- 停止
container
docker container stop containerIdOrContainerName
docker container start
- 重新開始停止中的
container
docker container start containerName
docker rm
刪除
container
docker rm containerID
刪除所有的
container
docker rm $(docker container ls -aq) -f
docker commit
- 將現有的 container 存成一個新的 image
docker commit -m 'imageMessage' -a 'AuthorName' containerSHA imageName:imageTag
Multi Stage (多階段構建)
Multi Stage Build
範本# 給予該層一個名字, storefront
FROM node:latest AS storefront
# 指定目前工作目錄
WORKDIR /usr/src/atsea/app/react-app
# 複製 context 中的 react-app 到當前目錄, 即上一行指令的 react-app
COPY react-app .
# 執行 npm install
RUN npm install
# 執行 npm run build
RUN npm run build
# 給予該層一個名字, 即 appserver
FROM maven:latest AS appserver
# 指定目前的工作目錄, 即 /usr/src/atsea
WORKDIR /usr/src/atsea
# 複製 context 中的 pom.xml 到當前位置, 即 atsea
COPY pom.xml .
# 執行以下指令
RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
# 複製 context 中的所有檔案到容器內的當前目錄下, 即 atsea
COPY . .
# 執行以下指令
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package -DskipTests
# 該是最終鏡像了, 沒給 alias
FROM java:8-jdk-alpine
# 執行以下命令
RUN adduser -Dh /home/gordon gordon
# 指令當前工作目錄
WORKDIR /static
# 從上面建構 storefront 中, 複製 /usr/src/atsea/app/react-app/build/ 當中的所有資料到當前工作目錄, 即 /static
COPY --from=storefront /usr/src/atsea/app/react-app/build/ .
# 指令當前工作目錄, 即 /app
WORKDIR /app
# 從上面建構的 appserver 中, 複製 /usr/src/atsea/target/AtSea-0.0.1-SNAPSHOT.jar 到當前工作目錄, 即 appserver
COPY --from=appserver /usr/src/atsea/target/AtSea-0.0.1-SNAPSHOT.jar .
# 指令 ENTRYPOINT, 該命令為容器啟動後默認一定會執行的命令, 無法被替換
ENTRYPOINT ["java", "-jar", "/app/AtSea-0.0.1-SNAPSHOT.jar"]
# CMD 在這個位置的角色為上面的 ENTRYPOINT 的 flag, 若在容器啟動指令輸入其他命令, 該 CMD 將會被替換掉
CMD ["--spring.profiles.active=postgres"]
-t
用來指定 image
的名字-f
可以用來指定名稱不是 Dockfile
的 Dockerfile
From
指定基礎 image
來源RUN
可以在 image
內執行 command
並建立新的 layer
,每一個 RUN
都會建立一層 layer
COPY
可以增加複製檔案到你的 image
內EXPOSE
暴露 APP 用的 port
ENTRYPOINT
設定當 image
被啟動為一個 container
時,預設執行的指令
Docker image pull
拉下
image
docker image pull ubuntu:latest
根據
digests
拉下image
docker image pull imageNane@sha256:specificDigests
docker image ls
列出下載過的
image
docker image ls
列出下載過的
image
以及digest
docker image ls --digests
docker rmi
刪除
image
docker rmi imageID
刪除所有的
image
docker image rm $(docker image ls -q) -f
docker build
- 建立
image
docker image build -t imageName:tagName .
docker image inspect
- 列出一個
image
的結構docker image inspect inamgeID
docker save
- 將 image 存成映像檔
docker save -o outputFileName imageName:imageTag
-o
代表 output
docker logs
- 查 log
docker logs -f containerID
Docker push
首先, tag 本地的 image 一個可以用來推上 DockerHub 的名字
docker tag localImageName:localTagName userAccount/toBeTaggedImageName:toBeTaggedImageTagName
推上 DockerHub
docker push userAccount/taggedImageName:taggedImageTag
Docker-Compose
安裝 docker-compose
- 安裝
Docker Compose
, 儘管我們可以從官方的ubuntu 倉庫
安裝Docker Compose
,但因為最新的版本中有很多細小的版本差異,所以我們從Docker GitHub
來安裝。 先到官方頁面確認版本,並且視需求更新下面指令的版本號。
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose |
設定權限
sudo chmod +x /usr/local/bin/docker-compose
確認
Docker-compose
版本docker-compose --version
建立
yaml
檔案vim docker-compose.yml
輸入內容如下:
my-test:
image: hello-world建立一個
container
docker-compose up
輸出理應如下:
建立一個 Swarm
- 開啟
docker swarm
模式上面的docker swarm init \
--advertise-addr 0.0.0.1:8080 \
--listen-addr 0.0.0.1:8080IP
跟PORT
自己訂的--advertise-addr
: 指定別的節點要連接這個 manager 時該使用的IP
以及port
。這不是個必要的選項,但是你可以對哪個IP
被使用有完全的控制權,並且你也可以訂一個不存在於節點上的IP
,像是負載平衡的IP
--listen-addr
: 讓你可以指定用來聽 swarm
traffic 的 IP
以及 port
,通常他會跟 --advertise-addr
相同,但如果你想要限制 swarm
在特定的 IP
,就特別有用。 還有一種情況,當 advertise-addr
是一個遠端的 IP
,像是平衡負載器,那這個也是必要的。
建議總是使用兩個附加選項。
從一個
node
開始swarm mode
,並且設為 leaderdocker swarm init \
--advertise-addr yourInternalIP:yourPort \
--listen-addr yourInternalIP:yourPort取得新增
manager
的 tokendocker swarm join-token manager
輸出大概如下:
docker swarm join \ |
- 取得新增
worker
的 tokendocker swarm join-token token
輸出大概如下:
docker swarm join \ |
重新產生 token
docker swarm join-token --rotate managerOrWorker
開啟並且登入一台新的
instance
, 輸入上面的 token 還有自己的 IP 位址docker swarm join \
token SWMTKN-1-0uahebax...c87tu8dx2c \
10.0.0.1:2377 \
advertise-addr yourInternalIP:yourPort \
listen-addr yourInternalIP:yourPort不管你是想加入成為
manager
或是workder
,只要輸入相對應的 token 就可以加入。在 Leader 的
node
上可以查看swarm
的詳細資料docker swarm node ls
離開當前的
swarm
docker swarm leave --force
開啟一個 SERVICE
- 要開立
service
首先必須確定,swarm
已建立。docker service create --name web-fe \
-p 8080:8080 \
--replicas 5 \
nigelpoulton/pluralsight-docker-cidocker service create
: 建立一個service
--name
: 指定service
的名稱-p
: 指定container
內以及連接外部的port
--replicas
: 在這個服務內,至少要有 5 個container
nigelpoulton/pluralsight-docker-ci
:image
以及tag
開立 service
之後, swarm
會一直的監看真實的狀態是否跟我的理想的狀態一致,如果一致的話那很好,如果不, swarm
會採取相對應的動作。
舉例來說,如果五個 container
裡面有一個關閉了, swarm
會自動在啟動一個
查看
service
清單docker service ls
查看
service
內的任務狀態docker service ps serviceName
更詳盡的資訊
docker service inspect --pretty serviceName
擴展規模
docker service scale web-fe=10
刪除
service
docker service rm web-fe
建立一個 overlay
network
docker network create -d overlay uber-net
連接到相同 overlay
network
的container
, 儘管他們的docker host
連接的網路不同,彼此也可以互相溝通連接。列出
network
資料docker network ls
刪除一個
network
docker network rm networkName
依據指定的
network
建立一個新的服務docker service create --name uber-svc \
--network uber-net \
-p 80:80 --replicas 12 \
nigelpoulton/tu-demo:v1--network
: 指定network
滾動升級 rolling update
滾動升級運行中的服務
docker service update \
--image nigelpoulton/tu-demo:v2 \
--update-parallelism 2 \
--update-delay 20s uber-svcdocker service update
: 升級service
--image
: 升級的image
來源--update-parallelism 2
: 一次升級兩個container
--update-delay 20s uber-svc
: 每批次的等待時間為 20 秒 , 需等當前批次的升級完成,時間才會開始計算。 最後指定要升級的service
名稱查看上次升級的參數
docker service inspect --pretty serviceName
如上圖,前一次升級的參數都會被保留下來,除非你再次升級去覆蓋它
Composer
- 利用
container
安裝Composer
docker run --rm -v $(pwd):/app composer install
--rm
: 當container
關閉後,自動刪除-v
: 使用volumes
$(pwd):/app
:$(pwd)
表示當前資料夾,/app
表示container
裡頭一個叫做app
的資料夾, 所以這個指令代表:
前後的兩個資料夾會在container
關閉之前,同步所有資料composer install
: 安裝composer
所以這個指令實際上做的事情,就是從 Docker Hub
拉下官方的 composer image
,然後開啟一個 container
並執行安裝, composer 會依照資料夾內 composer.json
或 composer.lock
來安裝相對應的 package 。 package 會被安裝在 app 這個資料夾內,但因為 volumes
的關係,所以兩個資料夾會同步, $(pwd)
內也會有安裝的 package 。 當安裝結束後, container
關閉,因為 --rm
的作用, container
會自動刪除。
利用 Docker-compose 部署 Laravel
安裝 docker-compose
- 環境為
Ubuntu 18.04
- 安裝
Docker Compose
, 儘管我們可以從官方的ubuntu 倉庫
安裝Docker Compose
,但因為最新的版本中有很多細小的版本差異,所以我們從Docker GitHub
來安裝。 先到官方頁面確認版本,並且視需求更新下面指令的版本號。
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose |
- 設定權限
sudo chmod +x /usr/local/bin/docker-compose
利用 Docker 來安裝環境
MySQL
安裝 MySQL , 並指定連接一個外部不同的 port 號 , 像是 52000
docker run --name serviceName -e MYSQL_ROOT_PASSWORD=yourPassword -d -p 52000:3306 mysql:5.7
docker run
: 啟動一個 container--name
: 指定這個服務的名稱-e MYSQL_ROOT_PASSWORD
: 指定環境參數-d
: 使這個服務跑在 container 當中-p
: 指定外跟內的 port 號, container 內部的 3306 連接外部的 52000mysql:5.7
: 指定 image 以及 tag連接本地安裝的 MySQL 以及 Docker container 內的 MySQL
本地安裝的
sudo mysql -uroot
Docker Container
mysql -h 127.0.0.1 -uroot -p2434 -P52000
製作 Docker image
- 時區問題
我的第一個目標,是利用 Docker commit 來做一個專屬的 image。簡單來說,就是起一個純淨的 container ,然後在這個 container 裡頭部署完之後,再使用 docker commit 將這個 container 變成一個 image , 結果發現在安裝php7.2-imagick
中會出現Configuring tzdata
,會彈出一個視窗並要求選擇時區,如下圖
後來找到解決方法,是在安裝 php7.2-imagick
之前就把時區設定好,所以在一開始就加入
export DEBIAN_FRONTEND=noninteractive && apt-get install -y tzdata && ln -fs /usr/share/zoneinfo/Asia/Taipei /etc/localtime && dpkg-reconfigure --frontend noninteractive tzdata |
MySQL 問題
接下來,又遇到一個問題,在我利用我製作好的 image 開一個 container 時, MySQL 無法成功啟動,會一直出現 Failed
後來的解決方法非常的奇怪,我是到 /var/www/mysql/mysql 中,下chown -R mysql:mysql .
的指令,然後它就好了…
可問題是,我仔細地確認過,在我下這指令之前,這個資料夾下的所有 user 以及 group 早就已經是 mysql:mysql 了Apache 以及 MySQL 無法設定自動重啟的問題 所以我們必須要在 container 裏頭啟動這些服務,需要啟動的服務如下:
- Apache
- MySQL
所以從目前的進度看來, container 啟動之後,我們必須要執行三個指令,如下:
chown -R mysql:mysql /var/www/mysql/mysql |
沒想到實際執行之後,我們遇到了一個新的問題…
Container 自動退出的問題
Container 的特性,是只要 command 執行完畢後,就會自動退出。 container 一旦退出了,我們原本建構的環境當然也就不在了。
我們怎麼可以容許這種事情發生呢?
因此,我們需要給 container 一個會一直持續存在的指令,好比是 /bin/bash該怎麼樣讓 container 在啟動的時候又執行多個指令呢?
在 container 啟動時, 我們需要執行多個指令來啟動 container 裡面的服務,但是 entrypoint 只能帶一個指令進去,所以我們要寫一個 shell script ,然後當 container 開啟之後去執行這個 shell script ,當然,這個 shell script 裡頭的指令就是上述提到的指令,如下:chown -R mysql:mysql /var/www/mysql/mysql
service apache2 restart
service mysql restart
/bin/bash
假設這個 shell script 叫做 test.sh ,然後放在 /usr/sbin/ 之下,那我們的 docker 指令如下:
docker run -dt --entrypoint "/usr/sbin/test.sh" -p 8880:80 --name containerName yourAccount/imageName:tagName |
ENV
man 指令
Docker 為了縮小 image 大小,預設不產生 man 說明文件。 在安裝 man 以及 man-pages 之前,需要先將此設定改掉
- 修改設定
Docker 為了縮小 image 大小,預設不產生 man 說明文件。 在安裝 man 以及 man-pages 之前,需要先將此設定改掉vi /etc/yum.conf
將以下這行 comment 掉
tsflags=nodocs |
安裝
yum install man-pages -y; yum install man -y
更新 mandb
mandb
安裝
vim
套件測試yum install vim
測試
man vim
可以用了
Q & A
當執行 Docker build 時, 如果不想要 context 中的某些資料夾或檔案被上傳到 docker daemon 去, 可以怎麼做? 建立一個 dockerignore 檔案, 並將不想上傳的檔案或資料夾加進去
如果不想使用預設的
dockerfile
, 可以怎麼做?docker -t -f dockerFileNameYouWant .
在 Docker CLI, 哪一個 flag 可以指定環境變數?
-e
在 Docker CLI, 哪一個 MYSQL 的 flag 可以允許空的密碼?
-e MYSQL_ALLOW_EMPTY_PASSWORD=yes
在 Docker CLI, 哪一個 flag 可以指定 volume?
-v
如何列出 volume 清單?
docker volume ls
如何列出指定 volume 訊息?
docker volume inspect volumeName
Docker 中, 預設的網路模式是? Bridge
可透過何種方式證明 Docker 預設容器可互聯互通? 在容器內取得 ip, 並使用 ping
當使用 –link 來連接到一個容器時, 實際上容器做了什麼事, 讓我們可以直接使用名字連接? Docker 在 /etc/hosts 裡頭將 IP 以及該容器名稱做連結
Docker 當中,
--link
是單向還是雙向的? 單向Docker 當中,
--network
是單向還是雙向的? 雙向docker –network host 只在哪一個 OS 上有用 Linux
docker –network container 的效果? 與指定的 container 共用網路
docker –network host 的效果? 與當前宿主機同網路, 換言之, 不需 port binding
docker –network none 的效果? 不為容器配置任何網路
以下的 Docker command 會輸出什麼? Hello, Cloud Man 。 環境變量
name
已經被值Cloud Man
替換掉了ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"以下的 Docker command 會輸出什麼? Hello, $name 。 環境變量沒有被替換
ENV name Cloud Man
ENTRYPOINT ["/bin/echo", "Hello, $name"]以下的 Docker command 中, 如果要使輸出使用環境變量, 該怎麼修改? 在
/bin/echo
跟Hello, $name
之間新增 command-c
ENV name Cloud Man
ENTRYPOINT ["/bin/echo", "Hello, $name"]Docker 中, apt-get update 和 apt-get install 建議放在同一個 RUN 指令中執行, 為什麼? Docker 會使用 Cache 如果指令沒有改變的話。 要是將這兩個指令分開了, 當執行到
apt-get update
時, 由於指令沒有變更, 所以 docker 使用緩存, 但是apt-get install
這層的指令變了, 可能會變成使用很久之前的緩存來安裝新的套件的情況, 這樣就找不到套件了。Docker 中, CMD 允許被使用者替換嗎? 允許
Docker 中, 如果 CMD 已有設定, 但 docker run 之後沒有指令命令, 那 container 會執行哪一個命令? CMD
如果 Dockerfile 中有多個 CMD, 哪一個為準? 只有最後一個 CMD 有效
CMD 有幾種格式? 三種
CMD 有哪三種格式? exec, shell, CMD [“param1”, “param2”]
在 Docker image 中, CMD 設定為 [“/bin/echo”, “Hello World”], 執行
docker run -it [image] /bin/bash
時, 會怎麼樣? 會只執行/bin/bash
Docker 中, ENTRYPOINT 有幾種格式? 兩種?
Docker 中, ENTRYPOINT 有哪兩種格式? exec, shell
Docker 中, ENTRYPOINT 的參數可以被動態替換掉嗎? 不行
在 Docker image 中, ENTRYPOINT 的設定為 [“/bin/echo”, “Hello”], CMD 為[“world”], 當我執行容器
docker run -it [image]
, 輸出為? Hello world在 Docker image 中, ENTRYPOINT 的設定為 [“/bin/echo”, “Hello”], CMD 為[“world”], 當我執行容器
docker run -it [image] Ray
, 輸出為? Hello Ray在 Docker image 中, ENTRYPOINT 為 shell 格式時, CMD 跟 docker run 的參數會? 被無視
在 Dockerfile 中, 哪三個指令會增加新的層數? RUN, ADD, COPY
在多階段構建中, 如何從指定層數 COPY 東西過來當層 藉由
AS
給該層一個名字, 然後使用COPY --from NAME
在 Docker 中, 如何使用 ENV 來更新 PATH 環境變量? 如下
ENV PATH /new/directory:$PATH
在 Docker 中, 當 COPY 的內容變了, 緩存是否會失效? 會哦
使用 docker-compose 部署 Laravel-LEMP
下載專案並安裝依賴
下載專案
git clone https://github.com/laravel/laravel.git laravel-app
進到資料夾
cd laravel-app
安裝依賴套件
-v
同步當層目錄與容器內的 /app- 執行命令 composer install
--rm
當容器關閉時, 自動刪除容器- 容器建立時, 外頭的
laravel-app
會與容器內的/app
同步, 這時候在容器內部的/app
執行 composer install, 安裝在容器內部/app
資料夾內的 composer 套件會即時的同步到外頭的laravel-app
資料夾內。 執行完畢後, 容器沒有其餘的任務, 因此容器會關閉,--rm
會自動刪除容器 - 更多 docker composer 的應用可參考官方文件
docker run --rm -v $(pwd):/app composer install |
- 更改權限
sudo chown -R $USER:$USER ~/laravel-app
建立 Docker Compose 檔案
建立並打開 docker-compose 設定檔
vim ~/laravel-app/docker-compose.yml
在
docker-compose
檔案中, 你將會自定義三個服務:app
,webserver
, 以及db
。 在檔案中輸入以下的代碼, 別忘了將MY_SQL_ROOT_PASSWORD
替換成你自己的密碼
# 版本 |
- app:
- 運行 Laravel
- build 客制鏡像
digitalocean.com/php
, 下面會有建立的 dockerfile - 使用客製的鏡像
digitalocean.com/php
, - 將當前工作目錄設在了
/var/www
- webserver:
- 使用官方
nginx:aline
鏡像 - 將容器內的 80 以及 443 port 接到宿主機的 80 以及 443 port
- 使用官方
- db:
- 使用官方
mysql:5.7.22
鏡像 - 定義一些環境變數, 包含資料庫名稱, 資料庫密碼, 這部分可以依個人需求更改
- 將容器內的 3306 接到宿主機的 3306 port
- 使用官方
- 我們把容器名稱跟服務名稱定義成一樣, 如果我們不定義容器名稱, Docker 會自動使用歷史上有名的人物的名稱來命名
- 我們為不同容器群組定義了專屬的 network, 位於相同 network 下的容器可以互相溝通, 反之則不行, 這確保了高等級的安全性, 不同類型的容器群不可以互相溝通, 像是前端只能跟前端溝通, 後端跟後端
建立 Dockerfile
# 使用官方 php:7.3-fpm |
PHP 設定檔
現在我們需要建一個 PHP 設定檔來同步宿主機以及容器內
建立資料夾
mkdir ~/laravel-app/php
設定檔
vim ~/laravel-app/php/local.ini
設定檔內容範例, 你可以添加其他設定
# 單檔的最大上傳限制
upload_max_filesize=40M
# 整個 post 的最大限制
post_max_size=40M
Nginx 設定檔
建立資料夾
mkdir -p ~/laravel-app/nginx/conf.d
建立設定檔
vim ~/laravel-app/nginx/conf.d/app.conf
範例設定檔內容, 可視需求添加
server {
# 監聽 80 port
listen 80;
# 尋找 index.php index.html
index index.php index.html;
# error log 位置
error_log /var/log/nginx/error.log;
# access log 位置
access_log /var/log/nginx/access.log;
# 資源的默認位置
root /var/www/public;
# 如果請求是 php 結尾的話, 進到 location
location ~ \.php$ {
# 尋找 uri, 若沒找到則 404
try_files $uri =404;
#
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
設定 MySQL
建立資料夾
mkdir ~/laravel-app/mysql
建立設定檔
vim ~/laravel-app/mysql/my.cnf
輸入設定檔內容, 可自行添加
[mysqld]
# 產生 log
general_log = 1
# log 位址
general_log_file = /var/lib/mysql/general.log
運行容器以及修改 env 設定
建立 .env
cp .env.example .env
運行容器
docker-compose up -d
查看容器
docker ps
修改 .env 檔
docker-compose exec app vim .env
DB_CONNECTION=mysql |
產生 key
docker-compose exec app php artisan key:generate
開啟 cache
留言