如何在“docker build”期间更新 Docker 映像中的 /etc/hosts 文件
Posted
技术标签:
【中文标题】如何在“docker build”期间更新 Docker 映像中的 /etc/hosts 文件【英文标题】:How to update /etc/hosts file in Docker image during "docker build" 【发布时间】:2016-11-13 03:50:30 【问题描述】:我想在“docker build”期间更新我的/etc/hosts
文件。
我在 Dockerfile 中添加了以下行,但它既没有更新 /etc/hosts
文件也没有给出任何错误。
RUN echo "192.168.33.11 mynginx" >> /etc/hosts
我需要更新/etc/hosts
。有人可以就此提出建议吗?
【问题讨论】:
你在使用 boot2docker 来执行你的 docker build 吗? 不,我使用的是 docker 1.8 的 Linux 版本。 当您将镜像作为容器运行时,它的 /etc/hosts 是否不变?还是您指的是您的 Linux 主机 /etc/hosts? 在 docker build 映像成功构建期间。但是当我使用相同的映像运行容器并检查 /etc/hosts 文件时,没有更改。 【参考方案1】:对于更新版本的 docker,这可以通过 docker-compose 及其 extra_hosts
directive 来完成
添加主机名映射。 使用与
docker run
client--add-host
parameter 相同的值(应该已经可用于 docker 1.8)。
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
简而言之:在运行容器时修改/etc/hosts
,而不是在构建容器时。
使用 Docker 17.x+,你有一个 docker build --add-host
提到 below,但是,正如 issue 34078 和 this answer 中所评论的:
构建期间的
--add-host
功能旨在允许在构建期间覆盖主机,但不会将该配置保留在映像中。
提到的解决方案确实参考了我上面建议的 docker-compose:
运行内部 DNS;您可以设置在守护程序中使用的默认 DNS 服务器;这样,每个启动的容器都会默认自动使用配置的 DNS使用 docker compose 并向您的开发人员提供
docker-compose.yml
。
docker compose 文件允许您指定启动容器时应使用的所有选项,因此开发人员只需 docker compose up 即可使用他们需要设置的所有选项来启动容器。
【讨论】:
我想更改 docker 镜像中的 /etc/hosts。 @PrakashSingh 我同意,但这似乎并不容易做到。 @PrakashSingh 你可以通过docket exec -it <container name> /bin/bash
在机器上打开一个bash实例,然后用你喜欢的命令行编辑器(vim、emacs、nano、echo)更新/ect/host下的docker容器主机'' . >>/>).
@PrakashSingh 是的,我们可以(听起来很熟悉......)。但是当我们通过构建镜像而不是运行容器来更改主机条目时,它看起来就像 Docker 的一种黑客攻击。 Docker 网络设计是应用程序驱动的(来自 docker.com)。由于 hosts 入口是 docker 网络的一部分,我们最好在从镜像运行容器时定义它。如果你真的需要添加一些hosts入口,你不要每次都通过build image来添加它们,你将它们添加到base image中一次。这是最佳做法。
在 docker build --add-host:cran.rstudio.com 期间解决 rocker/shiny install.packages 的问题:您不能在RUN
步骤中使用echo
修改映像中的主机文件,因为当您从映像启动容器时,docker daemon 将维护文件(/etc/hosts)及其内容(主机条目) .
但是可以使用以下方法来实现相同的目的:
ENTRYPOINT ["/bin/sh", "-c" , "echo 192.168.254.10 database-server >> /etc/hosts && echo 192.168.239.62 redis-ms-server >> /etc/hosts && exec java -jar ./botblocker.jar " ]
这里要注意的关键是使用 docker 文档建议的 exec
命令。使用 exec 将使 java 命令成为容器的 PID 1。 Docker 中断只会对此做出响应。
见https://docs.docker.com/engine/reference/builder/#entrypoint
【讨论】:
泰!这是一个很好的解决方案 如果您正在寻找 kubenetes 解决方案,您可以使用 hostAliases。 kubernetes.io/docs/concepts/services-networking/… 就像 docker compose extra_hosts。 更准确地说,ENTRYPOINT
不是图像指令。它仅在我们从该镜像运行容器时标记一个入口点,这意味着主机条目仅在容器运行后才存在。我不认为这个要求是必要的。一定是有什么误会。【参考方案3】:
我认为 docker 最近在 docker build 中添加了 --add-host
标志,这真的很棒。
[编辑] 所以这个功能更新在17.04.0-ce
有关如何将docker build
与--add-host
标志一起使用的更多详细信息,请访问:https://docs.docker.com/edge/engine/reference/commandline/build/
【讨论】:
--add-host
功能在 CentOS 上的 Docker 12 上可用。
我想强调“带有这个标志的主机只在构建过程中使用;它故意不应该保留在镜像中”github.com/moby/moby/issues/34078【参考方案4】:
由于这仍然是 Google 中的第一个答案,我将提供可能的解决方案。
来自here 的命令出人意料地为我工作(Docker 1.13.1,Ubuntu 16.04):
docker exec -u 0 <container-name> /bin/sh -c "echo '<ip> <name> >> /etc/hosts"
【讨论】:
不相关但仍然有价值。谢谢。 当你重新启动容器时,它会被原来的容器覆盖!!!【参考方案5】:你可以在运行docker的时候用下面的命令来做
docker run [OPTIONS] --add-host example.com:127.0.0.1 <your-image-name>:<your tag>
在这里,我将 example.com
映射到本地主机 127.0.0.1
及其工作。
【讨论】:
【参考方案6】:如果这对任何人有用,HOSTALIASES
环境变量对我有用:
echo "fakehost realhost" > /etc/host.aliases
export HOSTALIASES=/etc/host.aliases
【讨论】:
你不是把 docker 和 kubernetes 搞混了吗?我在 docker 文档中没有看到任何 HOSTALIASES 变量【参考方案7】:您可以在 docker run 期间使用 --add-host 选项。
对于您的情况,请使用: docker run --add-host mynginx:192.168.33.11 [image_name]:[tag]
这将更新您的 /etc/hosts
您可以使用以下命令进行检查:
docker exec -it [container_id] sh如果 sh 不适合你,那么你可以试试 bash 或 /bin/sh 或 /bin/bash
cat /etc/hosts【讨论】:
【参考方案8】:我刚刚创建了一个 sh 脚本并在启动 docker 上运行它。
在此脚本中,我启动所有服务并更新主机文件:
在 Dockerfile 上:
CMD /tmp/init_commands.sh & sleep infinity
init_comands.sh
any other commands...
echo "192.168.11.5 XXXXXXX" >> /etc/hosts
echo "192.168.11.6 XXXXXXY" >> /etc/hosts
echo "192.168.11.7 XXXXXXZ" >> /etc/hosts
【讨论】:
【参考方案9】:Tis is me Dockefile
FROM XXXXX
ENV DNS_1="10.0.0.1 TEST1.COM"
ENV DNS_1="10.0.0.1 TEST2.COM"
CMD ["bash","change_hosts.sh"]`
#cat change_hosts.sh
su - root -c "env | grep DNS | akw -F "=" 'print $2' >> /etc/hosts"
信息
用户必须su
【讨论】:
【参考方案10】:通过在 docker run 而不是 docker build 期间挂载文件,以下对我有用
docker service create --name <name> --mount type=bind,source=/etc/hosts,dst=/etc/hosts <image>
【讨论】:
使用卷添加文件会增加复杂性,并且每个主机都必须拥有该文件。【参考方案11】:使用以下方式运行容器的快速答案:
docker exec -it <container name> /bin/bash
一旦容器打开:
cd ..
然后
`cd etc`
然后你就可以了
cat hosts
或:
apt-get update
apt-get vim
或任何你喜欢的编辑器并在vim中打开它,在这里你可以修改你的启动ip为0.0.0.0
【讨论】:
以上是关于如何在“docker build”期间更新 Docker 映像中的 /etc/hosts 文件的主要内容,如果未能解决你的问题,请参考以下文章
为啥 docker build 中的 COPY 未检测到更新
Dockerfile: Docker build 无法下载包: centos->yum, debian/ubuntu->apt-get 内网后面