前言
大多数人可能都遇到过这样一个问题,在本地开发好功能后,部署到服务器,或者其他人拉到本地接着开发时,会出现功能用不了的情况。
大多数时候是由于系统不同,依赖出现差异而导致的。因此,为了解决这个问题,基于 Docker 构建统一开发环境的需求便产生了。
使用 Docker 的好处
部署方便:平常要搭建环境常常需要耗费几个小时,而且,对于团队协作时来说,每有新人进来,都需要浪费这可以避免的时间,而且搭建环境时,也常常会产生的各种问题,导致项目代码运行异常。如果使用了 Docker 的话,只需最开始的人写好开发容器,其他人只需要 pull 下来,即可完成项目环境的搭建,能有效避免无意义的时间浪费。
隔离性:我们时常会在一台电脑部署多个项目环境,若是直接安装的话,彼此间有可能会造成干扰,比如一个项目需要 Node.js 14,有的又需要 Node.js 12,若是直接在本机部署的话,总是不能共存的,而是用 Docker 的话,则可以避免该问题。Docker 还能确保每个应用程序只使用分配给它的资源(包括 CPU、内存和磁盘空间)。一个特殊的软件将不会使用你全部的可用资源,要不然这将导致性能降低,甚至让其他应用程序完全停止工作。
实现
安装 Docker
Linux
我是用的是 Arch Linux,所以以下安装方法是以 Arch Linux 为基础,其他发行版也大同小异,只是换成其包管理工具而已。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ sudo pacman-mirrors -i -c China -m rank $ sudo pacman -S docker $ sudo groupadd docker $ sudo usermod -aG docker $USER $ docker run --rm hello-world
Windows 10
Windows 10 下安装 docker 比较简单,有如下几种方式:
手动下载安装
点击以下 链接 下载 Docker Desktop for Windows。
下载好之后双击 Docker Desktop Installer.exe
开始安装。
1 $ winget install Docker.DockerDesktop
运行
在 Windows 搜索栏输入 Docker 点击 Docker Desktop 开始运行。
Docker 启动之后会在 Windows 任务栏出现鲸鱼图标。
等待片刻,当鲸鱼图标静止时,说明 Docker 启动成功,之后你可以打开 PowerShell/CMD/Windows Terminal 使用 Docker。
macOS
使用 Homebrew 安装
Homebrew 的 Cask 已经支持 Docker Desktop for Mac,因此可以很方便的使用 Homebrew Cask 来进行安装:
1 $ brew install --cask docker
手动下载安装
如果需要手动下载,请点击以下 链接 下载 Docker Desktop for Mac。
请注意下载对应芯片类型的软件,M1 和 Intel 芯片所对应的版本不通用。
如同 macOS 其它软件一样,安装也非常简单,双击下载的 .dmg 文件,然后将那只叫 Moby 的鲸鱼图标拖拽到 Application 文件夹即可(其间需要输入用户密码)。
运行
从应用中找到 Docker 图标并点击运行。
运行之后,会在右上角菜单栏看到多了一个鲸鱼图标,这个图标表明了 Docker 的运行状态。
每次点击鲸鱼图标会弹出操作菜单。
之后,你可以在终端通过命令检查安装后的 Docker 版本。
编写 Dockerfile
安装完 Docker 之后,接下来我们便可以来编写我们自己的项目开发环境了。本文将以前端开发环境为例,构建 Dockerfile。
包含环境:
node.js 14.17
npm 6.14
yarn 1.22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 FROM ubuntuMAINTAINER Caster "[email protected] " ENV DEBIAN_FRONTEND noninteractiveARG TZ=Asia/ShanghaiENV TZ ${TZ}RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone USER rootRUN sed -i "s/security.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list && \ sed -i "s/archive.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list && \ sed -i "s/security-cdn.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list RUN apt-get clean RUN apt-get update && apt-get install -y \ zsh \ vim \ wget \ curl \ python \ git-core RUN git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh \ && cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc \ && git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom} /plugins/zsh-autosuggestions \ && git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom} /plugins/zsh-syntax-highlighting \ && sed -i 's/^plugins=(/plugins=(zsh-autosuggestions zsh-syntax-highlighting z /' ~/.zshrc \ && chsh -s /bin/zsh RUN useradd --create-home --no-log-init --shell /bin/zsh -G sudo me RUN adduser me sudo RUN echo 'me:password' | chpasswd USER meRUN git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh \ && cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc \ && git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom} /plugins/zsh-autosuggestions \ && git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom} /plugins/zsh-syntax-highlighting \ && sed -i 's/^plugins=(/plugins=(zsh-autosuggestions zsh-syntax-highlighting z /' ~/.zshrc ENV NVM_DIR /home/me/.nvmENV NODE_VERSION v14RUN mkdir -p $NVM_DIR && \ curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash \ && . $NVM_DIR /nvm.sh \ && nvm install ${NODE_VERSION} \ && nvm use ${NODE_VERSION} \ && nvm alias ${NODE_VERSION} \ && ln -s `npm bin --global` /home/me/.node-bin \ && npm install --global nrm \ && nrm use taobao USER meRUN echo '' >> ~/.zshrc \ && echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc \ && echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc RUN curl -o- -L https://yarnpkg.com/install.sh | bash; \ echo '' >> ~/.zshrc && \ echo 'export PATH="$HOME/.yarn/bin:$PATH"' >> ~/.zshrc USER rootRUN echo '' >> ~/.zshrc \ && echo 'export NVM_DIR="/home/me/.nvm"' >> ~/.zshrc \ && echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc USER rootRUN echo '' >> ~/.zshrc \ && echo 'export YARN_DIR="/home/me/.yarn"' >> ~/.zshrc \ && echo 'export PATH="$YARN_DIR/bin:$PATH"' >> ~/.zshrc ENV PATH $PATH:/home/me/.node-binENV PATH $PATH:/home/me/.yarn/binUSER rootRUN rm -rf /var/lib/apt/lists/* WORKDIR /var/www
编写完 Dockerfile 后,构建即可:
1 docker build -t frontend/react:v1 .
构建完之后可以直接运行:
1 2 3 4 5 # 以 me 身份运行,推荐方式 docker run --user=me -it frontend/react:v1 /bin/zsh # 以 root 角色运行 docker run -it frontend/react:v1 /bin/zsh
编写 docker-compose.yml
在开发时,我们寻常需要多个容器配合使用,比如需要配合 mysql 或其他容器使用时,使用 docker-compose.yml 可以更好的组织他们。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 version: '2' services: react: build: context: . dockerfile: react/Dockerfile tty: true ports: - 30000 :3000 volumes: - ./react/www:/var/www networks: - frontend mysql: image: mysql:5.7 ports: - 33060 :3306 volumes: - ./mysql/data:/var/lib/mysql - ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d environment: - MYSQL_ROOT_PASSWORD=password networks: - frontend networks: frontend: driver: bridge
启动容器
编写玩上述 Dockerfile
和 docker-compose.yml
后,即可愉快的开始开发了!
1 2 3 4 5 6 7 8 cd frontenddocker compose up -d docker compose exec --user=me react /bin/zsh
为了测试容器间是否能相互访问,可以使用编写如下文件,数据库需自行创建:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const mysql = require ('mysql' )const connection = mysql.createConnection({ host : 'mysql' , user : 'root' , password : 'password' , database : 'test' , }) connection.connect(); connection.query(`SELECT * FROM users` , function (error, results, fields ) { if (error) throw error; console .log(results) }) connection.end();
之后运行,即可看到结果:
1 2 $ node index.js [ RowDataPacket { id: 1, name: 'Caster' } ]
总结
使用 Docker 来搭建开发环境十分方便,一次搭建,即可在许多机器上多次使用,即使是要重装系统,也不必在重复配置。
如不喜欢写 Dockerfile 的话,也可以直接开启一个容器,然后进入容器配置完后,使用 docker save/export 导出即可。
源码:https://github.com/MoeCasts/dockerfile-frontend