hot*_*oup 9 node.js docker dockerfile docker-compose
我的项目目录结构:
myapp/
src/
Dockerfile
docker-compose.yml
docker-deploy.sh
wait-for-it.sh
.env
Run Code Online (Sandbox Code Playgroud)
wait-for-it.sh著名的等待脚本的副本在哪里?
我的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"]
Run Code Online (Sandbox Code Playgroud)
并且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
Run Code Online (Sandbox Code Playgroud)
和我的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:
Run Code Online (Sandbox Code Playgroud)
我的样子.env:
DB_PASSWORD=1234
DB_USER=root
DB_PORT=5432
Run Code Online (Sandbox Code Playgroud)
当我从项目根目录运行以下命令行时:
docker-compose --env-file .env up --build
Run Code Online (Sandbox Code Playgroud)
我得到:
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.
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?错误是来自脚本本身、来自 中wait-for-it.sh配置不当的指令,还是来自实际运行的 Node/JS 应用程序?CMDDockerfilemy-service
应用@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.
Run Code Online (Sandbox Code Playgroud)
因此,它正在旋转数据库(postgres)没有问题,但由于某种原因,脚本仍然存在与权限相关的问题docker-deploy.sh。
正如@derpirscher的评论和我的评论中所指出的,问题之一是脚本的许可以及它们应该被称为ENTRYPOINT(not CMD) 的方式。
考虑您的Dockerfile的替代代码:
\nFROM node:16\n\nWORKDIR /usr/src/app\n\nCOPY package*.json ./\nCOPY wait-for-it.sh ./\nCOPY docker-deploy.sh ./\n\n# Use a single RUN command to avoid creating multiple RUN layers\nRUN chmod +x wait-for-it.sh \\\n && chmod +x docker-deploy.sh \\\n && npm install --legacy-peer-deps\n\nCOPY . .\n\nRUN npm run build\n\nENTRYPOINT ["./docker-deploy.sh"]\nRun Code Online (Sandbox Code Playgroud)\ndocker-deploy.sh脚本:
\nFROM node:16\n\nWORKDIR /usr/src/app\n\nCOPY package*.json ./\nCOPY wait-for-it.sh ./\nCOPY docker-deploy.sh ./\n\n# Use a single RUN command to avoid creating multiple RUN layers\nRUN chmod +x wait-for-it.sh \\\n && chmod +x docker-deploy.sh \\\n && npm install --legacy-peer-deps\n\nCOPY . .\n\nRUN npm run build\n\nENTRYPOINT ["./docker-deploy.sh"]\nRun Code Online (Sandbox Code Playgroud)\n有关Docker shell 入口点中内置的需求的更多背景信息,请参阅另一个 SO 问题。exec
另请注意,该exec ...命令行是在 shell 脚本内编写的(而不是直接以ENTRYPOINT / CMDexec 形式),这是使用参数扩展的关键因素。
\n换句话说:在问题的修订版 2中,该"${DB_HOST}:${DB_PORT}"参数是按字面意思理解的,因为ENTRYPOINT / CMDexec 形式中没有发生 shell 插值。
关于docker-compose.yml:
\n#!/bin/sh\n\n# call wait-for-it with args and then start node if it succeeds\nexec ./wait-for-it.sh -h "${DB_HOST}" -p "${DB_PORT}" -t 300 -s -- node start\nRun Code Online (Sandbox Code Playgroud)\n请注意,在此 Docker 设置中,wait-for-it主机应该是postgres(数据库的 Docker 服务名称),而不是0.0.0.0nor localhost。因为该wait-for-it脚本充当客户端,尝试连接到环境docker-compose网络中的指定 Web 服务。
0.0.0.0有关(服务器端、包罗万象的特殊 IP)和localhostDocker 上下文之间差异的更多详细信息,请参阅我的另一个 SO 答案。
(\xc2\xa7):最后但并非最不重要的一点是,ports: [ "${DB_PORT}:${DB_PORT}" ]应该删除这些行,因为 Compose 服务不需要它们进行通信(这些服务只需要属于一个公共 Compose 网络并使用其他 Compose 服务的主机名),同时直接在主机上暴露一个这样的端口会增加攻击面。
为了跟进我的评论ls -l docker-deploy.sh; file docker-deploy.sh,建议在您的目录中运行myapp/作为调试步骤(顺便说一句:稍后可以随意执行此操作,然后评论记录):
假设 Docker 中可能存在与@Lety指出的类似的意外错误:
\n我建议只替换(在 Dockerfile 中)该行
\n# version: \'3.7\'\n# In the Docker Compose specification, "version:" is now deprecated.\n\nservices:\n my-service:\n build: .\n # Add "image:" for readability\n image: some-optional-fresh-tag-name\n # Pass environment values to the entrypoint\n environment:\n DB_HOST: postgres\n DB_PORT: ${DB_PORT}\n # etc.\n # Add network spec to make it explicit what services can communicate together\n networks:\n - postgres-network\n # Add "depends_on:" to improve "docker-run scheduling":\n depends_on:\n - postgres\n\n postgres:\n # container_name: postgres # unneeded\n image: postgres:14.3\n environment:\n POSTGRES_PASSWORD: ${DB_PASSWORD}\n POSTGRES_USER: ${DB_USER}\n POSTGRES_DB: my-service-db\n PG_DATA: /var/lib/postgresql2/data\n volumes:\n - pgdata:/var/lib/postgresql2/data\n networks:\n - postgres-network\n # ports:\n # - ${DB_PORT}:${DB_PORT}\n # Rather remove this line in prod, which is a typical weakness, see (\xc2\xa7)\n\nnetworks:\n postgres-network:\n driver: bridge\n\nvolumes:\n pgdata:\n # let\'s be more explicit\n driver: local\nRun Code Online (Sandbox Code Playgroud)\n和
\nRUN chmod +x wait-for-it.sh \\\n && chmod +x docker-deploy.sh \\\n && npm install --legacy-peer-deps\nRun Code Online (Sandbox Code Playgroud)\n并直接在主机上的终端中运行:
\nRUN npm install --legacy-peer-deps\nRun Code Online (Sandbox Code Playgroud)\n如果这不起作用,您可能需要提供另一个有用的信息:您的操作系统是什么,您的 Docker 包名称是什么?(例如 docker-ce 或 podman\xe2\x80\xa6)
\n| 归档时间: |
|
| 查看次数: |
12175 次 |
| 最近记录: |