问题描述
想要使用Docker在生产环境部署他的Express/React应用,但遇到了一些困难。他的项目结构如下:
– 一个server
文件夹:运行Express应用,端口为4000
– 一个web
文件夹:一个React应用,在本地运行时使用端口3000,在服务器上需要运行在端口80
– 在根目录下有一个docker-compose.prod.yml
文件
他目前的尝试如下:
– docker-compose.prod.yml
文件中运行一个Postgres服务(端口5432),以及web
和server
各自的Dockerfile
– 在web
和server
文件夹中各有一个Dockerfile
– 他在本地使用yarn build
构建了server
和web
文件夹,然后将所有内容传输到服务器上
– 在服务器上,他运行以下命令构建了两个镜像:docker build -f web/Dockerfile.prod -t app_web ./web
和 docker build -f server/Dockerfile.prod -t app_server ./server
– 最后,他运行了docker-compose -f docker-compose.prod.yml up
他遇到的问题如下:
1. server
容器抛出了Error: Cannot find module '...'
错误,尽管他在Dockerfile中运行了yarn install --production
(可能与卷有关)
2. 当他运行docker run -it -p 80:80 app_web
和docker-compose up
时,访问服务器IP地址时,web
容器的行为不同:在第一种情况下,应用显示正常;在第二种情况下,一个页面列出了web
文件夹中的内容(所有文件和文件夹)
他非常希望得到帮助,因为他对生产环境中的Docker使用还比较新(他是否应该使用docker machine?他的文件夹结构、docker-compose和Dockerfiles是否有问题?)
解决方案
首先,感谢您的详细描述,让我可以更好地理解您的问题。现在,让我们逐步解决您遇到的问题。
解决”Cannot find module”错误
这个问题可能是由于卷的使用方式导致的。您在server/Dockerfile.prod
中使用了以下配置:
FROM mhart/alpine-node:11 AS builder
WORKDIR /app/server
COPY package.json ./
RUN yarn install --production
COPY . .
FROM mhart/alpine-node
WORKDIR /app/server
COPY --from=builder /app/server .
CMD ["node", "/app/server/dist"]
在这个Dockerfile中,您将node_modules
目录包括在了镜像中,而且在第一个构建阶段中没有使用它。这可能导致构建的镜像中缺少一些依赖模块,从而在容器中运行时导致”Cannot find module”错误。
为了解决这个问题,您可以尝试在第一个构建阶段中使用yarn install
,然后将node_modules
目录复制到第二个构建阶段中。以下是修改后的server/Dockerfile.prod
:
FROM mhart/alpine-node:11 AS builder
WORKDIR /app/server
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
FROM mhart/alpine-node
WORKDIR /app/server
COPY --from=builder /app/server .
CMD ["node", "/app/server/dist"]
解决Web容器行为差异问题
关于您在两种情况下web
容器行为的差异,有可能是由于您在docker-compose.prod.yml
文件中定义的端口映射导致的。
在第一种情况下,您运行了以下命令:
docker run -it -p 80:80 app_web
这里使用了端口映射,将容器的80端口映射到主机的80端口。因此,在访问服务器的IP地址时,应用能够通过主机的80端口进行访问。
在第二种情况下,您运行了以下命令:
docker-compose up
在docker-compose.prod.yml
中,您已经定义了端口映射:
ports:
- 80:80
这导致在运行docker-compose up
时,同样会将容器的80端口映射到主机的80端口。这可能导致与上述手动运行命令相同的行为。
关于使用docker-machine
根据您的描述,您的问题与docker-machine
并无直接关系。docker-machine
用于在远程服务器上创建和管理Docker主机,但在您的情况下,您似乎正在本地构建和运行镜像。
关于文件夹结构和Docker配置
根据您提供的信息,您的文件夹结构和Docker配置似乎是正确的。您在docker-compose.prod.yml
中定义了三个服务:db
、server
和web
,并且您在web
和server
文件夹中都有对应的Dockerfile。然而,问题可能出在镜像构建和容器运行的具体细节上,比如卷的使用、依赖模块的安装等。
总结
在解决问题时,请确保您的容器配置和Dockerfile正确,并注意卷的使用以及端口映射的设置。关于”Cannot find module”错误,您可以尝试使用我提供的修改后的server/Dockerfile.prod
。另外,确保您在构建镜像时包括了所有必要的依赖。
最后,关于不同行为的问题,检查您的`docker-compose.prod