创建多个Docker镜像

8
我是新手 Docker 用户,发现有大量的镜像在创建(可以通过 sudo docker images 命令查看),在 Stackoverflow 上找到一个解决方案:定期运行 sudo docker rmi $(sudo docker images -q) 命令以删除所有镜像。为什么会有这么多的镜像被创建?我的配置是否存在问题?
docker-compose.yml
nginx:
  build: ./nginx
  restart: always
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - /etc/letsencrypt/:/etc/letsencrypt/
  links:
    - node:node

node:
  build: ./node
  restart: always
  ports:
   - "8080:8080"
  volumes:
    - ./node:/usr/src/app
    - /usr/src/app/node_modules

nginx的Dockerfile如下:

FROM nginx:alpine

COPY nginx.conf /etc/nginx/conf.d/default.conf

Node.js的Dockerfile如下:

FROM node:9.3.0-alpine

WORKDIR /usr/src/app

COPY package*.json /usr/src/app/

RUN npm install --only=production

COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

网站/应用程序运行良好。除了定期删除所有容器、镜像,然后运行:sudo docker-compose up --build -d
3个回答

6
图片是不可变的,因此您进行的任何更改都会创建一个新的图片。由于您的 compose 文件指定了构建命令,当您启动容器时,它将重新运行构建命令。如果您使用 COPYADD 包含的任何文件发生更改,则不再使用现有的图片缓存,并且将构建一个新的图片而不删除旧图片。
请注意,我建议在 compose 文件中为您的图片命名,以便清楚地知道正在重建哪个图片。您可以观察 compose 构建输出以查看第一个未报告使用缓存的步骤,以了解正在发生什么。如果我要猜测,则 nodejs 中导致缓存失效并导致新图片生成的行可能是这行:
COPY . /usr/src/app

如果正在更改并导致重新构建的文件不需要在您的容器中使用,则使用 .dockerignore 文件来排除不必要的文件。

BMitch。谢谢。我认为复制命令的原因是应用程序(特定于Node.js文件)将不断更改。不是这样吗?而我的理解是图像是核心Node.js。我有.gitignore,其中没有像节点模块这样的标准同步内容。 - RmR
@Raj 你运行的是基于nodejs镜像构建的图像。每次更改代码后,它都将使用新内容重新创建。 - BMitch
这不就是Node Docker文件在做的吗?将程序中所做的更改复制到容器卷中。我的理解是,compose.yml 中指定的卷是外部于镜像的。对吗?所以无论在那里进行了更新都不会对镜像产生影响。我问这个问题的原因是该网站目前仅用于测试,而我可能会在本月底进入生产阶段。因此,我想掌握一下Docker。再次感谢您的迅速回复。 - RmR
@Raj 在compose文件中的卷会覆盖使用Dockerfile构建的镜像中运行的COPY。这是在开发环境中进行快速迭代的常见做法,但每次运行新的构建时,都会得到一个新的镜像。如果您只对主机卷的内容进行更改,并且只需要在本地查看它们,则可以跳过构建以避免创建另一个镜像。 - BMitch
@Raj 一旦你离开开发环境,你需要重新构建镜像并推送该构建的镜像。当你在生产环境中运行它时,你需要移除那个卷挂载。这样做的结果是你的代码将被嵌入到部署的镜像中。 - BMitch
谢谢 @BMitch。我会这样做的。 - RmR

4

在构建我的Dockerfile时,我遇到了同样的问题。

我找到了解决方案,请使用以下命令构建您的文件:

`docker build --rm -t <tag> .`

选项--rm在成功构建后删除中间容器。

-1

不应该创建“太多的图像”。

如果您想确保仅保留所需的一个(而无需每次重新构建所有内容),只需执行以下操作(如我在此处详细说明):

docker image prune

谢谢VonC。我定期执行类似的一组命令。停止所有容器。删除所有容器。删除所有镜像。修剪所有镜像。删除所有悬空容器等等。这是通过其中一个建议实现的。我的根本问题是为什么我必须这样做?以及是否因为我设置Docker的方式有误。在我看来,定期执行这些操作没有意义。 - RmR
@Raj 注意:你所描述的操作可以通过一个命令完成:docker system prune - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接