惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
T
Threatpost
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
V2EX - 技术
V2EX - 技术
D
Docker
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
The GitHub Blog
The GitHub Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
T
Troy Hunt's Blog
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
F
Full Disclosure
B
Blog
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Google DeepMind News
Google DeepMind News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
博客园 - 聂微东
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The Last Watchdog
The Last Watchdog
Recorded Future
Recorded Future
IT之家
IT之家
Project Zero
Project Zero
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

咸糖 - 自律者自由

2025 年终总结:降噪、重构与长期主义 在新加坡和新山吃过最好的食物(持续更新) 写给还在迷茫的你:我的三本大学回忆 2024 年终总结 Neovim: No Crash Incremental Selection 2022 年终总结 使用 neovim 作为 PDE(个性化开发环境) shell 是一个不错的生产力工具 使用二八法则省力地学习 awk 肉身翻墙新加坡安顿指南 关于编写可维护的代码的一些实践与想法 我为什么使用双向链接做笔记? 关于焦虑和拖延症 Golang: 如何处理日渐膨胀的 interface 使用番茄工作法来更好的利用你的时间 Unix 如何杀死一个进程和它的子孙进程? Golang: 让你的零值更有用 使用 Mock 和 Interface 进行 Golang 单测 关于 Golang Slice 的一些细节 总结一些计算机常用的原则 重新学习英语语法 上班族近期小半年入门投资基金组合的学习与实践经历 疫情期间的肉身翻墙新加坡指南 About me 软技能:大厂底层员工打工指南 软技能:我是如何获取知识与信息的? 分布式的令牌桶算法的实现 实现一个AtomicInteger GC root 在哪里? 什么是 Minor GC/Major GC 漏桶算法的设计与实现 剑指offer 单例模式 TCP 针对面试学习 Actor 如何处理阻塞消息 Akka 源码解析 How to learn scala AES 需要限制 SEED 长度 Java 如何区分==与.equals()方法 2018年年度总结 Java 集合扩容
使用 Docker Compose 建立你自己的开发环境
xiantang · 2022-05-05 · via 咸糖 - 自律者自由

【注意】最后更新于 December 29, 2025,文中内容可能已过时,请谨慎使用。

Docker 其实并不是一种新技术,而是一个新瓶装旧酒的工具。

其实我在大学上学的时候就用过 Docker,那个时候还是 17 年左右,Docker 还是如日中天的时候。只是用来起各种各样的轻量级应用,比如磁力链接下载器,个人网盘啥的。一直到不久的之前我对 Docker 的理解都还是比较模糊的,随着工作中需求的不断接触,我也不断的了解 Docker,于是打算写一篇文章总结一下最近对 Docker 的使用。

背景

其实是一直存在一个痛点就是,在我们的开发的时候有多个服务,并且服务之间是有相互的调用关系,但是如果是在本机中起来,服务总是可能会被各种端口占用,而且如果你的本机重启了,那么你的服务也会被关闭,是需要有一套好用的开发环境解决方案。

docker-compose 提供了将多个容器绑定起来的方式,可以很好的解决上述问题。

Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。使用 Compose,您可以使用 YAML 文件来配置应用程序的服务。然后,使用一个命令,您可以从您的配置中创建并启动所有服务。

也就是只需要简单的一句 docker-compose up 就可以启动项目中所依赖的相关服务,例如数据库、缓存、微服务等。

一直没有玩好的困境

其实在很久之前我就有尝试用 docker-compose 来构建我的开发环境,但是遇到了一些让我觉得不舒服的点,不过随着对 Docker 的理解的不断深入,我也慢慢的会玩明白了。

难以排查问题

第一点就是上手 Docker 之后难以排查问题,排查问题主要是分成两点,难以排查构建镜像中失败的问题,第二点就是难以排查容器启动失败的问题。

容器构建失败是非常常见的事情:

比如见下面这个 Dockerfile

1
2
3
4
FROM python:3.6 AS builder

COPY requirements.txt ./
RUN python -m pip install -r requirements.txt  https://pypi.tuna.tsinghua.edu.cn/simple

就比如说倘若 RUN python -m pip install -r requirements.txt https://pypi.tuna.tsinghua.edu.cn/simple 这个命令一直失败,那我们就可以 Dockerfile 改成上次成功的构建 + CMD[“bash”]

1
2
3
4
FROM python:3.6 AS builder

COPY requirements.txt ./
CMD ["bash"]

构建成功了之后,将这个容器使用直接起来,或者将 CMD 改写成 bash,就可以进入容器了,然后就可以看看到底是为什么 pip install 失败了。

docker run 命令是可以跟着参数将 CMD 改写的。

docker run [OPTIONS] IMAGE [COMMAND] [ARG...] docker run -ti --rm your_image bash

公司仓库的 private 库

工作中用 Golang 的时候经常会被各种私有库所挡住,比如 GithubGitlabGitee 等。 其实这个很简单,就是当发现 go mod download 下不来的时候,可以尝试改写你的 COMMAND 然后进到容器中进行排查。

对于用来自己开发的 Dockerfile,其实可以使用 .netrc 的方式来解决这个问题。 参见这个回答:

https://stackoverflow.com/questions/65824786/building-go-apps-with-private-gitlab-modules-in-docker

docker logs

如果想要查看容器的日志,可以使用 docker logs 命令,但是需要注意的是如果你的日志都是本地的 log 文件中,没有写到 stdout 的时候,使用 docker logs 是查不到问题的。

容器一起来就挂

很多时候你刚构建完成镜像,尝试 run 的时候,容器会一直退出,这个时候可以使用我上面提到的方法,把默认的 CMD 的命令改写成 bash,直接进去容器去跑一下你的命令,看看退出的日志就可以很轻松的查出问题了。

docker run -ti --rm your_image bash

编写 compose 的配置文件

Compose 有两个重要的概念:

  • services,这是一个 map,里面的 key 是容器的名字,value 是容器的配置。
  • projects,由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

可见,一个项目可以由多个服务 (容器) 关联而成,Compose 面向项目进行管理。

其实你可以把 Docker 的容器想的很简单,是一个普通操作系统的进程只不过有独立的网络,独立的文件系统,和自己单独的进程树。

所以在建设自己的微服务环境的时候,需要关注容器的网络是否是联通的,以及容器中的文件是否需要挂载到本地。

1
2
3
4
5
6
7
8
9
version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"

  redis:
    image: "redis:alpine"

这就是一个十分简单例子,把 web 和 redis 两个 service 关联起来,让两个容器在同一个项目中工作。

网络隔离

对于网络的联通,我们可以使甼 docker network create --driver bridge your_network 创建一个网络,然后把容器挂载到这个网络中。

docker compose 也可以定义网络,但是需要注意的是,如果你的网络是自己创建的,那么你需要在 docker-compose.yml 中指定网络的名称。

1
2
3
networks:
  your_network:
    driver: bridge

docker 是建议使用自己建立的网络,而不是使用默认的网络。

在这个 network 下的容器,docker 提供了 DNS lookup service。

1
2
3
4
5
6
7
8
  mysql:
    ... 
    networks:
      - your_network
  your_service:
    ...
    networks:
      - your_network

如果你的容器中有 ping,你就可以在 your_service 中使用 ping mysql 来检查是否能够 ping 过去。就是说可以通过用 docker-compose 中名字来访问到对应的容器。

也可以使用 busybox (将许多常见 [[UNIX]] 实用程序的微小版本组合成一个小型可执行文件。) 来检查容器的网络是否联通。

docker run -ti --rm --network=your_network busybox sh

常用的最佳实践

使用多阶段构建

使用多阶段构建,只会用最后一个阶段的来构建镜像,可以留下一个更加精简的 image-镜像

1
2
3
4
5
6
7
FROM python:3.6 
WORKDIR /APP

COPY . .
RUN python -m pip install -r requirements.txt  -i https://pypi.tuna.tsinghua.edu.cn/simple

CMD ["python","spider.py"]

可以改写成下面的格式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
FROM python:3.6 AS builder

COPY requirements.txt ./
RUN python -m pip install -r requirements.txt  -i https://pypi.tuna.tsinghua.edu.cn/simple

FROM python:3.6-slim 

COPY --from=builder /usr/local/lib/python3.6/site-packages /usr/local/lib/python3.6/site-packages
WORKDIR /APP

COPY spider.csv ./
COPY *.py ./

CMD ["python","spider.py"]

调整 Dockerfile 的顺序

调整 Dockerfile 的顺序,因为每一个步骤发生变化后,后面的步骤的缓存都会废纸,所以将变动较大的放在后面比较好。

下面的格式就是,当你改动了一个 py 文件中的一行代码,其实每次 docker build 都会把下边的依赖下载的缓存废弃,所以改动较大的放在后面。

1
2
3
4
5
6
7
FROM python:3.6 
WORKDIR /APP

COPY . .
RUN python -m pip install -r requirements.txt  -i https://pypi.tuna.tsinghua.edu.cn/simple

CMD ["python","spider.py"]

可以改成下面的格式:

1
2
3
4
5
6
7
8
FROM python:3.6

WORKDIR /APP
COPY requirements.txt ./
RUN python -m pip install -r requirements.txt  -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY spider.csv ./
COPY *.py ./
CMD ["python","spider.py"]

这样就可以改动 spider.py 中的代码没有增加新的依赖的时候,就能复用 pip install 的缓存。

最后

这就是我最近在使用 Docker 与 docker-compose 的时候的一些心得,希望能对大家有所帮助,本文将会不断地继续更新。

Ref: