[英]Docker Compose: executable file not found in $PATH: unknown
我的項目目錄結構:
myapp/
src/
Dockerfile
docker-compose.yml
docker-deploy.sh
wait-for-it.sh
.env
其中wait-for-it.sh
是著名的wait-for-it腳本的副本。
我的Dockerfile
:
FROM node:16
WORKDIR /usr/src/app
COPY package*.json ./
COPY wait-for-it.sh ./
COPY docker-deploy.sh ./
RUN chmod +x docker-deploy.sh
RUN npm install --legacy-peer-deps
COPY . .
RUN npm run build
ENTRYPOINT ["docker-deploy.sh"]
而docker-deploy.sh
是:
#!/bin/bash
# make wait-for-it executable
chmod +x wait-for-it.sh
# call wait-for-it with passed in args and then start node if it succeeds
bash wait-for-it.sh -h $1 -p $2 -t 300 -s -- node start
還有我的docker-compose.yml
:
version: '3.7'
services:
my-service:
build: .
postgres:
container_name: postgres
image: postgres:14.3
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USER}
POSTGRES_DB: my-service-db
PG_DATA: /var/lib/postgresql2/data
ports:
- ${DB_PORT}:${DB_PORT}
volumes:
- pgdata:/var/lib/postgresql2/data
volumes:
pgdata:
我的.env
看起來像:
DB_PASSWORD=1234
DB_USER=root
DB_PORT=5432
當我從項目根目錄運行以下命令行時:
docker-compose --env-file .env up --build
我得到:
Creating myapp_my-service_1 ... error
Creating postgres ...
Creating postgres ... done
ERROR: for my-service Cannot start service my-service: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "docker-deploy.sh": executable file not found in $PATH: unknown
ERROR: Encountered errors while bringing up the project.
到底是怎么回事? 錯誤是來自wait-for-it.sh
腳本本身,來自Dockerfile
中配置不當的CMD
指令,還是來自作為my-service
運行的實際 Node/JS 應用程序?
應用@ErikMD 建議的更改后的最新錯誤:
Creating postgres ... done
Creating myapp_my-service_1 ... error
ERROR: for myapp_my-service_1 Cannot start service my-service: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "./docker-deploy.sh": permission denied: unknown
ERROR: for my-service Cannot start service my-service: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "./docker-deploy.sh": permission denied: unknown
ERROR: Encountered errors while bringing up the project.
所以它正在啟動數據庫( postgres
)沒有問題,但由於某種原因,使用docker-deploy.sh
腳本仍然會出現與權限相關的問題。
正如@derpirscher和我的評論所指出的那樣,問題之一是您的腳本的許可以及它們應該被稱為CMD
ENTRYPOINT
。
考慮為您的Dockerfile 使用此替代代碼:
FROM node:16
WORKDIR /usr/src/app
COPY package*.json ./
COPY wait-for-it.sh ./
COPY docker-deploy.sh ./
# Use a single RUN command to avoid creating multiple RUN layers
RUN chmod +x wait-for-it.sh \
&& chmod +x docker-deploy.sh \
&& npm install --legacy-peer-deps
COPY . .
RUN npm run build
ENTRYPOINT ["./docker-deploy.sh"]
docker-deploy.sh腳本:
#!/bin/sh
# call wait-for-it with args and then start node if it succeeds
exec ./wait-for-it.sh -h "${DB_HOST}" -p "${DB_PORT}" -t 300 -s -- node start
有關在 Docker shell 入口點中需要內置exec
的更多上下文,請參閱此其他 SO 問題。
另外,請注意,這個exec...
命令行是寫在 shell 腳本中的事實(不是直接在ENTRYPOINT / CMD
exec 形式中)是使用參數擴展的關鍵因素。
換句話說:在您的問題的修訂版 2 中, "${DB_HOST}:${DB_PORT}"
參數被理解為字面意思,因為在ENTRYPOINT / CMD
執行形式中沒有發生 shell 插值。
關於docker-compose.yml :
# version: '3.7'
# In the Docker Compose specification, "version:" is now deprecated.
services:
my-service:
build: .
# Add "image:" for readability
image: some-optional-fresh-tag-name
# Pass environment values to the entrypoint
environment:
DB_HOST: postgres
DB_PORT: ${DB_PORT}
# etc.
# Add network spec to make it explicit what services can communicate together
networks:
- postgres-network
# Add "depends_on:" to improve "docker-run scheduling":
depends_on:
- postgres
postgres:
# container_name: postgres # unneeded
image: postgres:14.3
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USER}
POSTGRES_DB: my-service-db
PG_DATA: /var/lib/postgresql2/data
volumes:
- pgdata:/var/lib/postgresql2/data
networks:
- postgres-network
# ports:
# - ${DB_PORT}:${DB_PORT}
# Rather remove this line in prod, which is a typical weakness, see (§)
networks:
postgres-network:
driver: bridge
volumes:
pgdata:
# let's be more explicit
driver: local
請注意,在此 Docker 設置中, wait-for-it
主機應該是postgres
(數據庫的 Docker 服務名稱),而不是0.0.0.0
或localhost
。 因為wait-for-it
腳本充當客戶端,嘗試連接到環境docker-compose
網絡中的指定 web 服務。
有關 Docker 上下文中0.0.0.0
(服務器端,包羅萬象的特殊 IP)和localhost
之間差異的更多詳細信息,請參見我的其他 SO 答案。
(§) :最后但同樣重要的是, ports: [ "${DB_PORT}:${DB_PORT}" ]
行應該被刪除,因為 Compose 服務不需要通信(它們只需要屬於一個公共組合網絡並使用 Compose 服務主機名),而直接在主機上公開一個這樣的端口會增加攻擊面。
這有點像您計算機上的 shell :您輸入要執行的命令(只是命令的基本名稱),shell 會告訴您它是否找不到它 - 除非它不會告訴您它沒有$PATH
可能是(比較hash
實用程序)。
Now Docker ain't a shell and therefore the message is a bit more verbose (and that docker-compose is running docker is also adding in front of it):
錯誤:對於我的服務無法啟動服務我的服務:OCI 運行時創建失敗:container_linux.go:380:啟動容器進程導致:exec:“docker-deploy.sh”:在 $PATH 中找不到可執行文件:未知
所以 Docker 的部分是:
OCI 運行時創建失敗:container_linux.go:380:啟動容器進程導致:exec:“docker-deploy.sh”:在 $PATH 中找不到可執行文件:未知
這實際上是由於 Dockerfile 中的誡命:
ENTRYPOINT ["docker-deploy.sh"]
無論docker-deploy.sh
的(絕對)路徑在容器中,它的基本名稱( docker-deploy.sh
,再次)都無法在容器環境PATH
參數中找到(比較PATH (in) , Pathname Resolution , ETC。)。
使用容器內實際位於PATH中的可執行文件的基本名稱或絕對名稱(或相對於容器PWD環境參數又名工作目錄),以便它實際上可以執行(由 Docker 執行)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.