私信  •  关注

David Maze

David Maze 最近创建的主题
David Maze 最近回复了
4 年前
回复了 David Maze 创建的主题 » 从停止的docker容器中删除文件(不创建新图像)

总是 删除旧容器并运行新容器。这对每个应用程序和运行时都是一致的,不涉及如何手动将容器文件系统重置为初始状态。我几乎从不使用 docker start .

docker rm container_name
docker run -d --name container_name ...

如果您所在的环境中旧的pid文件可能会被留下(可能在绑定装载的主机目录中),则可以使用入口点包装脚本来清理它:

#!/bin/sh
rm -f /var/run/service.pid
exec "$@"

在Dockerfile中,将此脚本设置为 ENTRYPOINT .最后一行将运行图像的 CMD 作为主要的容器过程。

...
COPY entrypoint.sh . # must be executable, may already be there
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array form
CMD same as before

(你的问题提到 original_entrypoint.sh ; 如果已经进行了此设置,请在本地源代码树中编辑现有的入口点脚本,并添加 rm -f 在那里排队。)

3 年前
回复了 David Maze 创建的主题 » 如何将多个docker compose文件与扩展名字段和yml锚合并?

YAML锚点是单个文件的本地锚点。所以不,你不能在一个文件中定义一个锚,然后在另一个文件中引用它。

因为在使用时,Compose将合并设置 multiple Compose files 不过,你真的不需要这么做。如果你的基地 docker-compose.yml 档案上说

version: '3.8'
services:
  app:
    image: registry.example.com/app/${APP_TAG:-latest}
    healthcheck: { ... }

然后是你的发展 docker-compose.dev.yml

version: '3.8'
services:
  app:
    build: .

然后它将继承 image: 姓名和 healthcheck: 设置,如果两者都有 docker-compose -f 选项。

3 年前
回复了 David Maze 创建的主题 » Docker compose构建上下文和Docker卷

你应该删除它 volumes: 完全封锁。这是不必要的,可能会导致不一致的结果。

volumes:
     - ./app:/opt/app:delegated

这创造了一个 bind mount 当前位置 /opt/app 容器中的目录是 ./app 主机上的目录。Dockerfile在该目录中执行的任何操作(可能是整个安装过程)都是隐藏的。

绑定挂载不是Docker对象,它不会出现在像这样的地方 docker volume ls .

volumes:
     - notused:/opt/app/node_modules

这将替换文件的内容 node_modules 包含Docker内容的目录 named volume 。该命名卷的内容将优先于映像中的内容和绑定装入的父目录中的内容。据Docker所知,该目录包含不透明的用户数据,永远不会更新。也就是说,此设置会导致Docker忽略您的 package.json 文件,即使你重新运行 docker-compose build .

这种设置利用了Docker命名卷中的一种特殊情况:第一次将空命名卷装入容器时,Docker会将映像的内容复制到该卷中。这只会在第一次运行容器时发生(它不是对映像的一般传递),并且只在Docker命名的卷上发生(不在Kubernetes等其他运行时绑定装载或卷)。

许多设置使用 匿名卷 这里,只列出 /opt/app/node_modules 下面根本没有冒号 卷数: 。这与命名卷的行为相同,只是它没有名称。

volumes:
    - ./app/package-lock.json:/opt/package-lock.json

这是一个绑定装载,就像第一个案例一样,但它将文件装载到不同的目录中。这是我前面提到的“不一致的结果”可能出现的一个地方:如果您想使用构建的Docker映像,而不单独分发应用程序源,那么使用绑定挂载重新排列文件意味着有卷和无卷的文件系统布局不同。

我在这样的设置中经常看到的相关问题是执行一些安装步骤或在Dockerfile中移动文件。由于绑定挂载将所有内容都隐藏在容器中,因此所有这些工作都将丢失。想象你 RUN yarn build ; 该图像将包含一个 /opt/app/dist 目录,但绑定挂载隐藏了它。

通常,这种设置的动机是直接处理主机代码,而无需重建映像。但是,卷装载会隐藏映像构建中的所有内容,因此您也可以运行未经修改的 node 形象如果您正在运行代码绑定,那么它将装入未经修改的 节点 如图所示,您也可以在没有Docker参与的情况下运行Node。一个有用的开发设置可以是在Docker中运行数据库和其他依赖项,但在日常开发中使用普通的非容器语言运行时。

3 年前
回复了 David Maze 创建的主题 » Ubuntu-升级docker compose版本

这个 name: option

version: '3.8' # networks: { name: } requires a minimum of 3.5
networks:
    default:
        driver: bridge
        name: nssams_bridge

对于许多实际用途,您也可以让Compose选择网络的名称,因为您很少直接与它进行交互。你需要手册吗 docker network 命令或从另一个Compose文件引用网络,Compose将命名网络 projectname_default ,使用当前目录的名称作为项目名称。如果这对你来说是可以接受的,那么你可以删除这个 networks: 完全封锁。

3 年前
回复了 David Maze 创建的主题 » Supervisord只从Docker Compose开始

Docker容器只运行一个进程。如果需要在单个容器中运行多个流程,则需要一些流程管理器,如supervisord,但这通常被认为是一种反模式。标准的Docker Hub映像大致分为三种:基本操作系统映像( alpine , ubuntu ); 语言工具链和运行时( python , node , golang ); 以及运行一些实际程序的东西( postgresql , nginx ).在最后一种情况下,基本映像已配置为将程序作为单个主容器进程运行。

这意味着您可以将Dockerfile简化为

FROM nginx:1.21.1
COPY config/nginx.conf /etc/nginx/nginx.conf
COPY scripts/index.html /var/www/html/index.html

基本图像已经有了正确的 CMD 。您不需要文本编辑器、手册页或低级网络调试工具,因为这个容器唯一要做的就是为网页提供服务。


Docker容器只运行一个进程。有几种方法可以指定它。Dockerfile 命令 是默认值,但可以由Compose覆盖 command: 或者在 docker run 图像名称。也就是说,如果你 docker run --rm -it your-image /bin/bash ,交互式shell运行 而不是 这个 命令 在Dockerfile里。

这里最简单的答案就是不用担心运行交互式shell。 码头工人赛跑 没有命令的图像。 docker exec 节俭地它是一个非常有用的调试工具,但通常不是与容器交互的主要方式。

# do not override the command at the end
docker run -d -p 8080:80 nginx-custom:1.21.1

Docker容器只运行一个进程。当该过程完成时,容器退出。这意味着主容器进程需要是一个长期运行的前台进程;它不能是启动后台进程然后完成的脚本,也不能是“服务”类型的命令。

基地 nginx 图像会这样说

CMD ["nginx", "-g", "daemon off;"]

将Nginx服务器作为前台进程启动。

如果你 真正地 需要 run supervisord ,然后是主要的 命令 需要跑步 supervisord 而不是 service 命令,它需要一个 -n 选项在前台运行它。如果使用 命令 然后你自己负责把命令分解成文字。如果有嵌入的空间(如 daemon off; 在我的例子中 命令 在问题中)它们被视为一个带有空格include的单词,就像你在shell中引用它一样。

CMD ["supervisord", "-n"]

通常命令如下 服务 出于几个原因,不要在Docker工作。由于它们执行一些操作并立即返回,因此不适合作为主容器命令。如果你像问题中那样说“重新启动”,那么该服务之前不会运行。如果环境依赖于某个init守护进程,那么它也不会运行,并且 服务 systemctl 不能和它说话。不要尝试引入init系统,只需将该命令作为单个前台主容器进程直接运行即可。

5 年前
回复了 David Maze 创建的主题 » Docker用react应用编写网络问题

请记住,React应用程序总是在某些用户的浏览器中运行;它不知道Docker是否参与其中,并且无法访问或使用任何与Docker相关的网络设置。

在本地计算机上,我使用[…]192.168.99.100:8080查看json服务器

那么这也是您的React应用程序所需要的。

/api 到后端容器并将其他url转发到前端容器(或者更好的是,运行类似Webpack的工具,将React应用程序编译为静态文件并直接提供该服务)。如果您有这个设置,那么React应用程序可以使用一个路径 /api/v1/... 在没有主机的情况下,它将被解析为相对于浏览器认为的“当前主机”的任何内容,而该主机通常应该是代理。

5 年前
回复了 David Maze 创建的主题 » 角度应用程序未从docker-compose.yml文件运行

ports: 如果你设置了 network_mode: host . 此设置经常作为Docker网络问题的解决方案被抛出,在这里不应该是必需的。把那条线去掉。(您也可以安全地移除 container_name: image: 没有任何不良影响。)

6 年前
回复了 David Maze 创建的主题 » 有没有比我下面做的更好的方法来处理Docker的沙箱?

如果我反复多次这样做,我能不能假设每次运行都不会留下待清理的悬挂数据(最终耗尽磁盘空间)?

你保证每次跑步 留下待清理的悬挂数据:每个 docker build run创建一个新的图像,这些图像将一直保留到显式删除。包括完整的valgrind日志文件以及 Makefile

相反,您可以考虑是否可以直接使用 sandbox 图像,并使用 docker run -v docker run --rm 选项,当容器退出时自动清理容器。

6 年前
回复了 David Maze 创建的主题 » 重新启动docker compose并更新数据库

这个 docker-entrypoint-initdb.d 机制只在数据库容器第一次启动时运行,数据库为空。你需要明确 docker-compose rm 你身后的集装箱 docker-compose stop 它们将导致删除当前数据库,然后在新的空数据库中创建新的空表。

迁移 . 各种Docker数据库映像没有直接的迁移支持;这几乎总是打包在应用程序级数据库库中(例如,RubyonRails和Python的SQLAlchemy都有迁移工具)。

不管怎样,一旦有了迁移系统,最好使用它来创建初始的数据库表。 docker入口点initdb.d 对于创建初始用户或加载种子数据库转储之类的数据库级设置来说,这样做更有意义,但实际上,对于所描述的更改,您始终需要一个迁移系统。

6 年前
回复了 David Maze 创建的主题 » 使用不同于主机上的用户启动Docker容器

显示的Dockerfile将创建两个图像。第一个是平原 debian 与非根用户的映像。第二个忽略了第一个,是一个有点常规的Java映像。

您需要在同一个图像中执行这两个步骤。如果我要写你的案卷的话

FROM java:8
EXPOSE 8080

# (Prefer COPY to ADD unless you explicitly want its
# auto-unpacking semantics.)
COPY /target/juju-0.0.1.jar juju-0.0.1.jar

# Set up a non-root user context, after COPYing content
# in.  (Prevents the application from overwriting
# itself as a useful security measure.)
RUN groupadd -g 61000 app
RUN useradd -g 61000 -l -m -s /bin/false -u 61000 app
USER app

# Set the main container command.  (Generally prefer
# CMD to ENTRYPOINT if you’re only using one; it makes
# both getting debugging shells and later adopting the
# pattern of an initializing entrypoint script easier.)
CMD ["java","-jar","juju-0.0.1.jar"]

如果容器中的程序显示 Listening on 127.0.0.1 它可能无法从容器外部访问,您需要以某种方式配置它,以便它绑定或侦听0.0.0.0(所有接口)。

中的示例 the Cloud SQL Proxy documentation 有此选项:

/cloud_sql_proxy -instances=...=tcp:0.0.0.0:3306 ...

而0.0.0.0才是最重要的。

6 年前
回复了 David Maze 创建的主题 » Docker compose-包含命令行工具的容器

根据我的经验,Docker方法是第三种选择,将操作包装在一个HTTP facade中,让它一直运行。

Docker很好地支持HTTP路径(您可以使用其他容器 --name 例如,作为主机名),它很容易在其他环境中测试或模拟这还意味着,如果您确实需要对其中一个支持工具进行更新,您可以重新启动另一个容器;您不必关闭主应用程序来更新它。

Docker在处理其主要交互模式是命令行参数、stdin或stdout的进程时并不能很好地工作。特别是一个集装箱发射另一个集装箱 该容器需要通过主机进行不受限制的根访问 ,您需要使用DockerAPI,而不仅仅是启动子进程。

如果外部程序相当独立,那么将它们复制到Dockerfile中并将它们作为普通子进程调用就可以工作。您提到Java;如果您只为偶尔启动的某个对象添加一个完整的JVM,则会增加臃肿和复杂性。

6 年前
回复了 David Maze 创建的主题 » 从docker访问装入的卷以便在生成时安装作曲家/npm?

我认为最好的做法,以及我在专业上所做的,是在这种情况下根本不使用卷。我的档案 COPY 在生成时在应用程序代码中。我有一个正在工作的主机开发设置(唯一真正的主机依赖关系是节点本身;其他的都在 node_modules 如果有问题,我可以在本地环境中复制、调试和编写测试。只有这样我才能回到码头。

FROM ???
WORKDIR /var/www/app
COPY app/composer.json app/composer.lock ./
RUN composer install --ignore-platform-reqs --no-scripts
COPY app/ ./
...
CMD ["apache2ctl", "-DFOREGROUND"]

否则,Docker volumes有几点需要记住:

  • dockerfile中的所有内容都发生在 docker-compose.yml 文件甚至被考虑在内。如果您的目标是填充一个卷,那么就不能在Dockerfile中执行此操作(而这通常在Docker中很难实现;请使用本机主机工具)。

  • 如果将卷装入容器目录,它将完全隐藏已经存在的内容。我看到很多关于Dockerfiles的问题,它们只在本地容器中工作 /app 目录,然后绑定挂载本地源代码树;这基本上使Dockerfile成为no-op。

  • 如果你有 VOLUME 在Dockerfile中,不能再对图像中的目录进行任何更改(在你的问题中,跑步 composer 之后 音量 指令将不起作用。)

  • 无论卷是否声明为 音量 . 我建议你不要宣布 音量 在Dockerfiles中,尤其是对于包含代码的目录(您 希望 当容器被删除并重新创建时,这些将用新的图像代码更新)。

6 年前
回复了 David Maze 创建的主题 » 如何为CD的每个代码分支提供一个Docker容器

这是绝对可能的,虽然不是单靠Docker工具。你大概需要:

  1. 让ci系统用分支名称标记图像
  2. 让CD系统选择一个端口并在该端口上部署映像
  3. 建立一个 network load balancer 为您的服务重定向“正常”端口( 例如 ,对于http为80)到您部署到的特定端口
  4. 部署 Route 53 分支名称指向负载平衡器的DNS记录
  5. 当你注意到树枝已经消失时,撤销这些步骤

自从您指定了ec2之后,我已经引用了特定的aws子产品,但是相同的基本序列应该可以在任何环境中工作(甚至在步骤3和4中使用haproxy和bind的内部环境)。(另外,这个序列中唯一真正特定于Docker的是打包系统和为特定容器实例指定主机端口的统一方法。)

你可以考虑使用更高级的工具来管理这些事情。 Ansible 例如,将“模块”设置为 start Docker containers on remote hosts ,请 create AWS NLBs create Route 53 records 是的。 Terraform 可以管理云资源(但保持其状态与常规的自动重新部署保持一致可能很棘手)。

您还可以考虑更高级别的部署框架。这个部署序列基本上就是您访问 ECS ,例如。 Kubernetes 仍然是更大的投资,但作为标准选择,它的服务对象有能力 create load balancers ,和(带有附加组件) create the DNS record for you ;但同样,“推送映像并为其创建部署和服务”是在kubernetes中部署任何东西的完全普通的方式,而非默认分支没有什么特别之处。

6 年前
回复了 David Maze 创建的主题 » Docker compose in another directory影响其他容器

docker compose将名称前缀附加到它创建的所有内容,但默认前缀仅基于当前目录的基名。如果你有一个布局像

projectA
+-- docker
|   \-- docker-compose.yml
projectB
\-- docker
    \-- docker-compose.yml

然后两者 docker-compose 实例会认为项目名称只是 docker (包含 docker-compose.yml )并创建容器名称,例如, docker_postgres_1 .

您可以通过重命名目录中的一个来实现这一点,使用 docker-compose -p option setting a COMPOSE_PROJECT_NAME environment variable . 看到一个 docker-compose.yml文件 文件位于项目的顶层目录中,这可能有助于消除歧义。

6 年前
回复了 David Maze 创建的主题 » Docker:如何创建一个包含一些登录凭据的映像

不要试图在Docker映像中存储任何类型的凭据:任何拥有您的映像的人都可以窃取凭据。 而是在运行时注入凭据,可以使用卷或绑定装入的目录在容器运行期间持久化登录令牌。

无法安全地将数据存储在Docker映像中。任何人都可以轻松地 docker history 获取创建图像的命令列表,或 docker run --entrypoint=/bin/sh 得到根壳。即使在没有外壳的额外的最小图像上,任何能运行任何DOCKER命令的人都可以在主机上生根,并且可以在 /var/lib/docker 找到你想要隐藏的东西。

(另一个答案是输入登录dockerfile所需的用户名和密码 ENV 声明。那些将在那里,在纯文本,在 Docker历史 输出供任何人查看。)

如果需要在这样的容器运行中保留状态,可以使用Docker卷或主机绑定装载。这可能看起来像:

docker run -v $PWD/sampleprogram:/sampleprogram/credentials \
  archlinux/sampleprogram:latest \
  sampleprogram login
docker run -p 8080:8080 ... \
  -v $PWD/sampleprogram:/sampleprogram/credentials \
  archlinux/sampleprogram:latest

(假设Dockerfile以类似于 CMD ["sampleprogram", "connect"] 设置默认命令。)

6 年前
回复了 David Maze 创建的主题 » docker映像、docker compose和服务调用的公开端口的单一配置

这无关紧要:您可以在多个容器中运行服务器,这些容器都侦听同一端口,并将它们映射到主机上不同的已发布端口。

我会在Dockerfile中硬编码端口;说它总是端口9191。然后在 docker-compose.yml 可以设置的文件

slim-first:
  image: slim-image
  ports: ["9191:9191"]
slim-second:
  image: slim-image
  ports: ["9192:9191"]

这两个容器可以从主机上的不同端口访问。

(在Dockerfile中公开主要是文档;它有两个很少相关的副作用。 expose: 在Docker中,compose文件对您没有多大帮助。)

6 年前
回复了 David Maze 创建的主题 » 登陆Docker注册表后可以使用什么Docker命令?

除此之外,没有与远程注册表交互的标准cli命令 docker pull docker push . 注册表本身可能提供某种类型的ui(例如,amazonerc可以通过标准aws控制台列出图像),或者您的本地开发团队可能有一个wiki,列出通常可用的内容。

不能更改默认的Docker注册表。你很期待 例如 ubuntu 是真的 docker.io/library/ubuntu 而不是别的。

6 年前
回复了 David Maze 创建的主题 » 使用主机网络运行多个不同端口的mysql容器

如果使用主机网络是一项硬性要求,那么Docker空间中的任何东西都无法控制或限制服务使用或不使用的端口。您需要更改特定于服务的配置文件、环境变量或命令行参数,使其在其他地方侦听。

特别是对于侦听单个TCP端口的服务器(如大多数数据库和基于HTTP的服务器),默认的Docker Bridge/NAT设置应该可以正常工作;不需要其他设置,如主机网络和MacVLAN。如果您愿意使用标准设置,这一点很简单:

version: '3'
services:
  mysql:
    image: mysql
    ports: ['9999:3306'] # listen on host port 9999 instead
6 年前
回复了 David Maze 创建的主题 » 如何使用docker和python创建和跟踪处理链

例如,我会研究排队系统 RabbitMQ . 这将使您有四个队列,每个任务一个队列,并让您跟踪事物的位置,同时在每个可能的状态下有多个事物。您可以有四个独立的长时间运行的容器,它们都在其中一个队列中工作,如果您需要更多的处理能力(例如,分析阶段),您可以启动容器的多个副本。

当您布置问题时,它实际上听起来并不太复杂,您应该考虑在单个进程/脚本/容器中运行它的优点。(例如,从某个磁盘位置获取数据并将其复制到数据库的最后一步可能更容易与前面的步骤合并;如果整个管道减少以获取数据、处理数据并保存数据,则不将其称为管道可能更简单。)

你几乎绝对不应该 docker run docker exec 核心处理流程的一部分。如果您可以运行这些docker命令中的任何一个,那么您可以对主机系统执行任何操作:有一些主要的安全注意事项是您不愿意考虑的。根据您所处的环境,您可能还希望避免一些启动成本(例如,任何涉及jvm的东西仍然需要~永远才会出现)。长期运行的工作容器通常是更好的模型。

ls -l 上市 r 在第八列中,表示文件是世界可读的;目录 x 在第十列中,任何人都可以访问。从你发布的内容来看,没有什么是访问任何它无权访问的内容。

(世界可写 autoload.php 如果它允许对系统具有shell访问权限的任何人编写web服务器将运行的任意代码,则可能是危险的。)

6 年前
回复了 David Maze 创建的主题 » Docker容器未运行

一旦入口点完成(以任何形式),容器就退出。

一旦集装箱出口,你就不能 docker exec 投入其中。

如果你想得到一个外壳上的形象,你只是建立了戳在它周围,你可以

sudo docker run --rm -it --entrypoint /bin/sh starter

为了使运行起来稍微容易一些,您可以在dockerfile中将entrypoint更改为cmd。(Docker将运行entrypoint,将cmd作为命令行参数传递;或者如果没有entrypoint,只运行cmd。)

...
RUN chmod +x ./app.sh
CMD ["./app.sh"]

这样做之后,可以更容易地重写命令

sudo docker run --rm -it starter /bin/sh
6 年前
回复了 David Maze 创建的主题 » 为什么用自定义用户创建Docker容器来重新发布派生图像?

我有个申请

FROM openjdk:8-jre
COPY myapp.jar /
CMD ["java", "-jar", "/myapp.jar"]

现在,我想使用您的技术来拥有一个普通的非根用户。所以我要把这个文件改成

FROM my/openjdk:8-jre # <-- change the base image name
USER root             # <-- change back to root for file installation
COPY myapp.jar ./
USER user             # <-- use non-root user at runtime
CMD ["java", "-jar", "./myapp.jar"]

此外,假设有一个Java安全问题,我需要把所有的东西更新到一个更新的JRE。如果我使用的是标准的OpenJDK映像,我只需要确保 docker pull 更新了一个映像,然后重新生成应用程序映像。但如果我使用的是自定义中间映像,我需要先重建该映像,然后重建应用程序。这就是维护负担产生的原因。

在我的码头工人的照片里,我倾向于 RUN adduser 并指定 USER 在图像本身中。(它们不需要主目录或任何特定的shell,而且它们绝对不应该具有依赖主机的用户ID。)如果您大致上将Dockerfile视为具有三个“部分”来设置操作系统级依赖项、安装应用程序和定义运行时参数,我通常会将其在第一部分。

FROM openjdk:8-jre  # <-- standard Docker Hub image
RUN adduser user    # <-- add the user as a setup step
WORKDIR /app
COPY myapp.jar .    # <-- install files at root
USER user           # <-- set the default runtime user
CMD ["java", "-jar", "/app/myapp.jar"]

(假设您的应用程序存在安全问题。如果您已将文件作为根目录安装,并且正在以非根目录运行应用程序,则攻击者无法覆盖容器中已安装的应用程序。)

6 年前
回复了 David Maze 创建的主题 » 我可以运行一个Docker容器在IBM电源系统上进行x86构建吗?

您可能可以使用现有的构建方法和接近于未更改的脚本,但需要重新构建实际的图像。

您不能在通电时直接运行x86二进制文件(在非常低的级别上,机器代码的字节是不同的)。Docker不包含任何类型的虚拟化层;它执行了一系列的设置来将容器与主机隔离,然后直接在映像中运行二进制文件。

如果您的Jenkins安装程序有足够的参数用于图像名称和版本标记,那么您应该能够并行运行x86和电源设置;您需要在构建的图像名称或标记中对架构进行编码;例如, repo.example.com/app/build:20180904-power . (我不知道,如果你控制了所有的机器,其中一个或另一个会被认为更好。)如果你有一个私人回购,你可以在路径中更早地对其进行编码,最后得到像这样的图像名称 repo.example.com/power/build:20180904 .

您需要再次检查具有Docker图像引用的所有地方是否正确参数化了它(无论如何这是一个很好的实践)。包括任何直接的 docker run 命令;任何docker撰写或kubernetes yaml文件或类似的工件;以及 the FROM line of any Dockerfiles .

6 年前
回复了 David Maze 创建的主题 » 多级Docker构建的工件缓存

在构建图像的过程中,您不能使用卷,无论如何,Docker已经完成了您要求的缓存。如果你离开你的 Dockerfile 保持原样,不要尝试将代码添加到 docker-compose.yml ,您应该获得构建的javascript文件的缓存,并按预期访问重建。

当你跑步时 docker build Docker依次查看每一步。如果步骤的输入没有更改,步骤本身没有更改,并且添加的任何文件没有更改,那么Docker将重新使用以前运行该步骤的结果。在你的 文档文件 如果您只更改nginx配置,它将跳过所有的javascript构建步骤,并重新使用之前的结果。

(您已经掌握的另一种相关技术是通过两个步骤构建应用程序:第一个步骤是在类似 package.json yarn.lock 这将命名依赖项并安装依赖项;然后复制并构建应用程序。由于“安装依赖项”步骤经常是耗时的,并且依赖项变化相对较少,因此您希望鼓励Docker重用上一个构建的 node_modules 目录。)

6 年前
回复了 David Maze 创建的主题 » 无法启动Docker项目

如果您可以运行任何docker命令,那么您可以非常简单地将主机根目录:

docker run --rm -v /:/host busybox \
  cat /host/etc/shadow

此外,Docker容器经常在自己的容器空间中作为根运行,这意味着无论您选择向其公开主机文件系统的哪个部分,它们都可以作为任意用户ID进行任意更改。您可以使用 docker run -u 选择不同的用户ID,但您可以选择 任何 用户ID,甚至是属于共享系统上另一个用户的ID。

使用起来很合理 sudo 作为一种获得需要根权限的方法,这是一种典型的开箱即用的Docker配置。

一天结束时,唯一真正的入口是文件上的Unix权限。 /var/run/docker.sock . 这通常是模式0660所拥有的专用 docker 组。如果你不介意你的普通用户在没有任何控制的情况下读写任意的主机文件,你可以把自己添加到这个组中。这通常适用于开发人员的笔记本电脑;但对于任何类似于生产系统的东西,它都需要真正考虑其安全性的影响。

5 年前
回复了 David Maze 创建的主题 » Docker没有运行某些运行指令?

这个 Dockerfile VOLUME directive 大多数情况下只有令人困惑的副作用。除非你对它的作用和你想要它的原因一目了然,否则你应该删除它。

特别是,其中一个令人困惑的副作用是 RUN 写入卷目录的命令会丢失。所以当你在第7行说 VOLUME /sphinx , the RUN sphinx-quickstart 第15行尝试将其输出写入当前目录(声明的卷目录),因此输出内容不会持久化到图像中。

(将代码存储在卷中通常是不合适的;将其构建到映像中,以便稍后可以重用。你可以用 docker run -v 在任何容器端目录上绑定装载内容,而不管其是否声明为 体积 )

6 年前
回复了 David Maze 创建的主题 » Docker Compose上ssh的初始设置

最佳实践通常是不从容器进行出站ssh连接。如果要添加到容器中的是二进制代码或应用程序代码,请在Docker之外管理源代码管理设置,并将数据复制到图像中。如果应用程序需要运行其数据,请再次从外部获取并使用 docker run -v 把它注入容器。

正如您所说,安全地管理这个关键材料,并遵守sshs-unix权限要求,是非常棘手的。如果我真的没有选择,但要做这个ID,请编写一个入口点脚本,将私钥从绑定装载的卷复制到容器用户。 .ssh 目录。但我的第一选择是重新设计我的应用程序流,根本不需要这个。

6 年前
回复了 David Maze 创建的主题 » 在Docker的Django没有暴露在局域网中

简而言之:容器内的进程必须绑定到0.0.0.0,才能从容器外访问;但是您可以使用Docker Compose的 ports: 控制它实际可从何处访问的选项。如果你把它改成 "127.0.0.1:8000:8000" 它将无法从非主机访问。

docker容器运行 an isolated network . 典型的设置可能如下所示:

 ^^^
Router
  | 192.168.1.1
  +--------------------+-- ...
  | 192.168.1.2        | 192.168.1.3
/- Host -----------\   Host 2
|    172.17.0.1    |
|     |            |
|     | 172.17.0.2 |
|  Container       |
\------------------/

作为实施细节 每个容器都有自己的专用IP地址。这是在一个隔离的网络上:192.168.1.3/24上的第二个主机不知道172.17.0.0/16上的容器专用网络甚至不知道如何在那里路由流量。由于每个容器都有自己的专用网络堆栈,因此每个容器也有自己的概念,即 localhost 手段。

(将此关系图与直接在主机上运行的服务器进行比较。它可以在192.168.1.2上访问,但只能从同一个网络访问;路由器远端的客户机无法访问192.168.1.0/24专用网络,而且即使绑定到“所有接口”,服务器也无法从公共互联网访问。)

如果将容器进程设置为仅绑定到其自己的lo0接口127.0.0.1,则它将不接受来自172.17.0.2 eth0接口的入站流量,这意味着外部的任何东西都无法到达它。

如果将容器进程设置为绑定到0.0.0.0(“所有接口”),那么它将接受来自主机的流量,从172.17.0.1发送(可能是Docker0接口)。这与接受来自“整个网络”的流量不同,不过:正如前面所讨论的,主机2仍然不知道如何将流量路由到那里。

你可以使用 docker run -p 或者码头工人作曲 端口: 选项来限制Docker将向哪些接口发布端口。如果你改变 端口: “127.0.0.1:8000:8000” 然后,容器将可以从主机上的端口8000访问,但只能通过主机的环回接口访问;同样,主机2没有向进程发送数据包的路由。

6 年前
回复了 David Maze 创建的主题 » 获取python docker容器以与redis docker容器交互

做:

  • 显式地为应用程序创建Docker网络,并运行连接到该网络的容器。(如果您使用docker compose,这会自动发生,您不需要做任何事情。)

    docker network create foo
    docker run -d --net foo --name some-redis redis
    docker run -it --rm --net foo --name pyRed python-redis-py
    
  • 使用容器 --name 作为DNS主机名:连接到 some-redis:6379 到达集装箱。(在Docker中,服务块的名称也可以组成。)

  • 使外部服务的位置可配置,最有可能使用环境变量。在python代码中,可以连接到

    redis.Redis(host=os.environ.get("REDIS_HOST", "localhost"),
                port=int(os.environ.get("REDIS_PORT", "6379"))
    
    docker run --rm -it \
      --name py-red \
      --net foo \
      -e REDIS_HOST=some-redis \
      python-redis-py
    

唐:

  • docker inspect 找到容器专用IP地址的任何内容。在容器之间,您可以始终使用主机名,如上所述。容器专用IP地址无法从其他主机访问,甚至可能无法从某些平台上的同一主机访问。

  • 使用 localhost 在Docker中,任何情况下都需要从浏览器或其他正在运行的进程进行连接的特定情况。 直接地 在主机上(不在容器中)到您发布的端口 docker run -p 在同一主机上。(一般指_此容器_。)

  • 代码中的硬代码主机名是这样的;这使得在不同的环境中运行服务变得困难。(尤其是对于数据库,在Docker之外甚至在托管云服务中运行它们并不少见。)

  • 使用 --link 它已经过时了,而且是不必要的。

6 年前
回复了 David Maze 创建的主题 » 如何在dockerfile中为谷歌云设置守护进程服务

一般来说,您应该假设如下命令 service 只是不要在Docker工作。您希望容器的主进程是服务本身,这通常意味着直接运行服务器进程。 The Squid FAQ 暗示了一个类似

CMD ["squid", "-NCd1"]

尤其是在 -N 选项使其作为前台非守护进程运行。

(您还应该更喜欢JSON ISH表单 CMD ENTRYPOINT 如果可以的话。很多人更喜欢 入口点 我总是使用 CMD 如果它是一个选项,更容易在 docker run 时间,并允许一个入口点脚本的模式进行启动前初始化,然后运行 CMD )

6 年前
回复了 David Maze 创建的主题 » 如何将start参数传递给docker compose文件,比如docker run--opts?

大部分的 docker run 选项具有匹配项 Docker Compose options . 特别地, docker run --security-opt 地图到A security_opt: field .

db:
  image: 'mysql:8.0'
  security_opt:
    - 'seccomp:unconfined'
  et: cetera
6 年前
回复了 David Maze 创建的主题 » 如何设置正确的路径来复制多步骤Docker构建的文件?

Your first stage doesn't actually RUN the build command ,因此生成目录为空。将命令行更改为运行行。

一个提示:每个单独的行 docker build 序列生成自己的中间层,每个层都是可运行的Docker映像。你会看到输出

Step 6/8: CMD ["npm", "run", "build"]
 ---> Running in 02071fceb21b
 ---> f52f38b7823e

最后一个数字是有效的Docker图像ID,您可以

docker run --rm -it f52f38b7823e sh

看看照片里有什么。