<aside> 💡 本文主要面向 Docker 初学者或前端开发者。阅览本文前,请务必先了解 Docker 是什么,以及各种基本概念 (镜像、容器等)。

</aside>

Why & How?

我是一个开发环境洁癖主义者,各种开发环境之间的相互影响非常讨厌,因此我曾经几乎尝试过网上的所有解决方案,比如 GUI 虚拟机、Vagrant、WSL 等等,但这些都有或多或少的缺点,尤其是当我在使用 Windows 系统的时候,开发环境永远是一个痛点。而横向对比下来,Docker 或许是当下最优的解决方案了。虽然 Docker 设计初衷是为了方便进行部署和运维,但只要是能用在生产环境的家伙,当然也能用在开发环境。那 Docker 在开发环境究竟可以做哪些事呢?

  1. 我们可以把一些和系统联系不慎紧密的服务使用 Docker 托管,比如 MySQL、Redis、MongoDB 之类的数据库软件。当我们需要使用不同版本的 MySQL 时,只需要拉取一个新的镜像,起一个新的容器即可,而假如用 Homebrew 等包管理工具去管理多个版本的 MySQL 时,就不会像 Docker 这般优雅了。
  2. 我们也可以把一些配置异常复杂的软件跑在 Docker 里,比如 Gitlab 这样的巨型项目。
  3. 一些平台差异巨大的软件使用 Docker 托管是更好的选择。Nginx 可能是目前世界上最流行的 Web Server,而这种生而为 Linux 服务的软件在 Windows 下的表现并不好 (当然这应该不算是 Nginx 的错),这时候我们就可以使用 Docker 中的 Nginx,提供与生产环境几乎一致的体验。虽然 Docker 在 Windows,MacOS 和 Linux 上的表现并不完全一致,但绝大部分时间场景下其跨平台特性还是很够用的,能为我们省去很多烦恼。
  4. 我们甚至还可以把 Docker 当作一个虚拟机进行项目开发。借助目录、端口映射等功能,我们可以实现类似虚拟机一样的,在宿主机编写代码、在 Docker 容器中运行的效果。如果容器内的开发环境“脏”了,我们只需要重新起一个新容器即可。当然,这种方案会有性能损耗等一系列问题,用来做小一些小项目、或者学习一些新技术进行练手是可以的,但当项目体量足够大时,这种方案可能就会带来各种各样的问题。
  5. 如果需要其他同事的项目跑在本机进行联调,比如后端的 Java 或者 PHP 项目,那么可以让他们打成 Docker 镜像,前端同事只需要把镜像跑起来即可,无须本地搭建后端环境。

docker-compose.yml 以及数据库服务

以 Docker 最常见的托管 MySQL 为例,我们要创建一个能够使用的 MySQL 容器需要两条命令:

docker pull mysql
docker run --name some-mysql \\
  -v ./mysql/conf.d:/etc/mysql/conf.d \\
  -v ./mysql/datadir:/var/lib/mysql \\
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \\
  -d mysql

可以看到启动命令其实是比较繁琐的,况且这还是只有一个 MySQL 的情况。当我们有其他版本的 MySQL 或者其他服务需要一起使用时,单纯用命令行操作就显得非常繁琐了。因此我们也需要创建一个属于开发环境的 docker-compose.yml 文件用来管理一切我们需要用到的服务。

首先在你喜欢的位置创建一个文件夹,在其中添加 docker-compose.yml

version: "3.8"

services:
	mysql:
			# 启动后的容器名称
	    container_name: mysql
			# 需要使用的镜像及版本
		  image: mysql:latest
			# 总是自动重启
	    restart: always
			# 端口映射
	    ports:
	      - "3306:3306"
			# 数据卷映射
	    volumes:
	      - ./data/mysql:/var/lib/mysql
			# 镜像需要使用的环境变量
	    environment:
	      - MYSQL_ROOT_PASSWORD=pass
	      - TZ=PRC

接着我们只需要执行 docker compose up -d 就可以直接启动文件中的所有服务。我们还可以给启动命令添加服务名作为参数,表示仅启动指定的服务,比如 docker compose up -d mysql

按照这个思路,我们只需要在 docker-compose.yml 中添加自己需要的各种服务即可,比如 Redis、MongoDB 等。下面再给出一个添加了 Redis 和 MongoDB 的完整例子。注意,我们在这里使用了 redis:alpine 这个基础镜像,这是因为基于 alpine 这个 linux 发行版的 Docker 镜像体积非常小,没有特殊需求的话,应当尽可能选用 alpine 版本的镜像。

使用 Nginx

起步和初始化