前言
這是一份未整理過的 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版,可在以下的指令中自由取代stablesudo 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 CEsudo 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的shellubuntu: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
列出運行中的
containerdocker container ls列出所有的
container, 包含已停止的docker container ls -a
or
docker ps -a |
docker container stop
- 停止
containerdocker container stop containerIdOrContainerName
docker container start
- 重新開始停止中的
containerdocker container start containerName
docker rm
刪除
containerdocker rm containerID刪除所有的
containerdocker 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 的 DockerfileFrom 指定基礎 image 來源RUN 可以在 image 內執行 command 並建立新的 layer ,每一個 RUN 都會建立一層 layerCOPY 可以增加複製檔案到你的 image 內EXPOSE 暴露 APP 用的 portENTRYPOINT 設定當 image 被啟動為一個 container 時,預設執行的指令
Docker image pull
拉下
imagedocker image pull ubuntu:latest
根據
digests拉下imagedocker image pull imageNane@sha256:specificDigests
docker image ls
列出下載過的
imagedocker image ls列出下載過的
image以及digestdocker image ls --digests
docker rmi
刪除
imagedocker rmi imageID
刪除所有的
imagedocker image rm $(docker image ls -q) -f
docker build
- 建立
imagedocker 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建立一個
containerdocker-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離開當前的
swarmdocker 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 個containernigelpoulton/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


刪除
servicedocker service rm web-fe建立一個 overlay
networkdocker network create -d overlay uber-net
連接到相同 overlay
network的container, 儘管他們的docker host連接的網路不同,彼此也可以互相溝通連接。列出
network資料docker network ls刪除一個
networkdocker 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安裝Composerdocker 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 volumeNameDocker 中, 預設的網路模式是? 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-cENV 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/bashDocker 中, 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
留言