我们在开发中都会遇到这样的问题:在本地开发好功能后,部署到服务器,或者其他人拉到本地接着开发时,会出现功能无法使用的情况。

这些异常情况,大多数时候是因为系统不同而导致的依赖差异。因此,为了解决这个问题,就产生基于 Docker 构建统一开发环境的需求。

有关 docker 的基本知识,可以参照 docker教程

1. 使用 Docker 的好处

  • 部署方便

    我们平常搭建环境常常需要耗费很长时间。对于团队协作时来说,每有新人进来,都需要浪费这些可以避免的时间。而且搭建环境时,也常常会产生的各种问题,导致项目代码运行异常。如果使用了 Docker 的话,只需最开始的人写好开发容器,其他人只需要 pull 下来,即可完成项目环境的搭建,能有效避免无意义的时间浪费。
  • 隔离性

    我们时常会在一台电脑部署多个项目环境,若是直接安装的话,彼此间有可能会造成干扰,比如一个项目需要 Node.js 14,有的又需要 Node.js 12,若是直接在本机部署的话,总是不能共存的,而是用 Docker 的话,则可以避免该问题。Docker 还能确保每个应用程序只使用分配给它的资源(包括 CPU、内存和磁盘空间)。一个特殊的软件将不会使用你全部的可用资源,要不然这将导致性能降低,甚至让其他应用程序完全停止工作。

2. 安装 Docker

1) Linux 安装 Docker

以 Arch Linux 为例,其他发行版也大同小异,只是换成其包管理工具而已。

  1. # 设置国内镜像站,国内提速用的,可选操作
  2. $ sudo pacman-mirrors -i -c China -m rank
  3.  
  4. # 使用 Pacman 安装 Docker
  5. $ sudo pacman -S docker
  6.  
  7. # 建立 docker 用户组。默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。
  8. $ sudo groupadd docker
  9.  
  10. # 将当前用户加入 docker 组,退出当前终端并重新登录后生效
  11. $ sudo usermod -aG docker $USER
  12.  
  13. # 测试是否安装成功
  14. $ docker run --rm hello-world

2) Windows 10

Windows 10 下安装 docker 比较简单,有如下几种方式:

手动下载安装:

下载 Docker Desktop for Windows

下载好之后双击 Docker Desktop Installer.exe 开始安装。

使用winget安装:

  1. $ winget install Docker.DockerDesktop

运行 Docker:

在 Windows 搜索栏输入 Docker 点击 Docker Desktop 开始运行。

Docker 启动之后会在 Windows 任务栏出现鲸鱼图标。

等待片刻,当鲸鱼图标静止时,说明 Docker 启动成功,之后你可以打开 PowerShell/CMD/Windows Terminal 使用 Docker。

3) 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 的运行状态。

安装完成并启动后,我们可以在终端通过命令检查安装后的 Docker 版本。

  1. $ docker --version

3. Docker 换源

docker 默认的源是国外的,国内访问的话速度比较慢,因此可以换为国内源,提高镜像拉去速度。

1) Linux 换源

Linux 下的比较简单,创建个 deamon.json 文件写下配置就好:

  1. $ vi /etc/docker/deamon.json
  2.  
  3. # 输入镜像源
  4. {
  5. # 只换一个源也是可以的,可以直接用字符串,而不是数组。
  6. "registry-mirrors": [
  7. "https://registry.docker-cn.com",
  8. "http://hub-mirror.c.163.com",
  9. "https://docker.mirrors.ustc.edu.cn"
  10. ],
  11. }
  12.  
  13. # :wq 保存退出后重启 docker
  14. $ systemctl restart docker

2) Windows 和 Mac 换源

Windows 和 Mac 都是使用的 Docker Desktop,所以直接在 GUI 中配置即可。

打开 Docker 界面,点击 Docker Engine:

在右边输出框中,输入镜像源:

  1. {
  2. "registry-mirrors": [
  3. "https://registry.docker-cn.com",
  4. "http://hub-mirror.c.163.com",
  5. "https://docker.mirrors.ustc.edu.cn"
  6. ],
  7. }

4. 编写 Dockerfile

安装完 Docker 之后,接下来我们便可以来编写我们自己的项目开发环境了。本文将以前端开发环境为例,构建 Dockerfile。

包含环境:

  • node.js 14.17
  • npm 6.14
  • yarn 1.22
  1. # 前端开发中,时常需要使用 shell 命令,而有一个较为完整的环境比较重要,因此选择了使用 ubuntu 作为基础,若在意容器大小的话,可自行选择适用的基础镜像
  2. FROM ubuntu
  3. LABEL org.opencontainers.image.authors="codebaokur@codebaoku.com"
  4.  
  5. # 设置环境变量
  6. ENV DEBIAN_FRONTEND noninteractive
  7.  
  8. # 设置时区
  9. ARG TZ=Asia/Shanghai
  10. ENV TZ ${TZ}
  11.  
  12. RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  13.  
  14. # 用 root 用户操作
  15. USER root
  16.  
  17. # 更换阿里云源,在国内可以加快速度
  18. RUN sed -i "s/security.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list && \
  19. sed -i "s/archive.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list && \
  20. sed -i "s/security-cdn.ubuntu.com/mirrors.aliyun.com/" /etc/apt/sources.list
  21. RUN apt-get clean
  22.  
  23. # 更新源,安装相应工具
  24. RUN apt-get update && apt-get install -y \
  25. zsh \
  26. vim \
  27. wget \
  28. curl \
  29. python \
  30. git-core
  31.  
  32. # 安装 zsh,以后进入容器中时,更加方便地使用 shell
  33. RUN git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh && \
  34. cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc && \
  35. git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions && \
  36. git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting && \
  37. sed -i 's/^plugins=(/plugins=(zsh-autosuggestions zsh-syntax-highlighting z /' ~/.zshrc && \
  38. chsh -s /bin/zsh
  39.  
  40. # 创建 me 用户
  41. RUN useradd --create-home --no-log-init --shell /bin/zsh -G sudo me && \
  42. adduser me sudo && \
  43. echo 'me:password' | chpasswd
  44.  
  45. # 为 me 安装 omz
  46. USER me
  47. RUN git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh && \
  48. cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc && \
  49. git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions && \
  50. git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting && \
  51. sed -i 's/^plugins=(/plugins=(zsh-autosuggestions zsh-syntax-highlighting z /' ~/.zshrc
  52.  
  53. # 安装 nvm 和 node
  54. ENV NVM_DIR=/home/me/.nvm \
  55. NODE_VERSION=v14
  56.  
  57. RUN mkdir -p $NVM_DIR && \
  58. curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash && \
  59. . $NVM_DIR/nvm.sh && \
  60. nvm install ${NODE_VERSION} && \
  61. nvm use ${NODE_VERSION} && \
  62. nvm alias ${NODE_VERSION} && \
  63. ln -s `npm bin --global` /home/me/.node-bin && \
  64. npm install --global nrm && \
  65. nrm use taobao && \
  66. echo '' >> ~/.zshrc && \
  67. echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc && \
  68. echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc
  69.  
  70. # 安装 yarn
  71. RUN curl -o- -L https://yarnpkg.com/install.sh | bash; \
  72. echo '' >> ~/.zshrc && \
  73. echo 'export PATH="$HOME/.yarn/bin:$PATH"' >> ~/.zshrc
  74.  
  75. # Add NVM binaries to root's .bashrc
  76. USER root
  77.  
  78. RUN echo '' >> ~/.zshrc && \
  79. echo 'export NVM_DIR="/home/me/.nvm"' >> ~/.zshrc && \
  80. echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc && \
  81. echo '' >> ~/.zshrc && \
  82. echo 'export YARN_DIR="/home/me/.yarn"' >> ~/.zshrc && \
  83. echo 'export PATH="$YARN_DIR/bin:$PATH"' >> ~/.zshrc
  84.  
  85. # Add PATH for node & YARN
  86. ENV PATH $PATH:/home/me/.node-bin:/home/me/.yarn/bin
  87.  
  88. # 删除 apt/lists,可以减少最终镜像大小
  89. RUN rm -rf /var/lib/apt/lists/*
  90.  
  91. WORKDIR /var/www
  92. 编写完 Dockerfile 后,构建即可:
  93.  
  94. docker build -t frontend/react:v1 .
  95. 构建完之后可以直接运行:
  96.  
  97. # 以 me 身份运行,推荐方式
  98. docker run --user=me -it frontend/react:v1 /bin/zsh
  99.  
  100. # 以 root 角色运行
  101. docker run -it frontend/react:v1 /bin/zsh

5. 编写 docker-compose.yml

在开发时,我们寻常需要多个容器配合使用,比如需要配合 mysql 或其他容器使用时,使用 docker-compose.yml 可以更好的组织他们。

  1. version: '2'
  2. services:
  3. react:
  4. build:
  5. context: .
  6. dockerfile: react/Dockerfile
  7. tty: true
  8. ports:
  9. - 30000:3000
  10. volumes:
  11. - ./react/www:/var/www
  12. networks:
  13. - frontend
  14. mysql:
  15. image: mysql:5.7
  16. ports:
  17. - 33060:3306
  18. volumes:
  19. - ./mysql/data:/var/lib/mysql
  20. - ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
  21. environment:
  22. - MYSQL_ROOT_PASSWORD=password
  23. networks:
  24. - frontend
  25.  
  26. # 将容器置于同一 networks 即可直接通过容器名访问
  27. networks:
  28. frontend:
  29. driver: bridge

6. 启动容器

编写完上述 Dockerfile 和 docker-compose.yml 后,即可愉快的开始开发了!

  1. # 进入 docker-compose.yml 所在目录
  2. $ cd frontend
  3.  
  4. # 后台启动 docker-compose.yml 中所有容器,若容器没有构建则会先构建
  5. $ docker-compose up -d
  6.  
  7. # 进入 react 容器中,以便命令行交互
  8. $ docker-compose exec --user=me react /bin/zsh

为了测试容器间是否能相互访问,可以使用编写如下文件,数据库需自行创建:

  1. // index.js
  2. const mysql = require('mysql')
  3. const connection = mysql.createConnection({
  4. host: 'mysql',
  5. user: 'root',
  6. password: 'password',
  7. database: 'test',
  8. })
  9.  
  10. connection.connect();
  11.  
  12. connection.query(`SELECT * FROM users`, function (error, results, fields) {
  13. if (error) throw error;
  14. console.log(results)
  15. })
  16.  
  17. connection.end();

之后运行,即可看到结果:

  1. $ node index.js
  2. [ RowDataPacket { id: 1, name: 'Caster' } ]

7. 总结

使用 Docker 来搭建开发环境十分方便,一次搭建,即可在许多机器上多次使用,即使是要重装系统,也不必在重复配置。

如不喜欢写 Dockerfile 的话,也可以直接开启一个容器,然后进入容器配置完后,使用 docker save/export 导出即可。

参考资料:

1. Docker教程

2. Docker构建开发环境

如何使用Docker构建开发环境的更多相关文章

  1. [转]利用Docker构建开发环境

    利用Docker构建开发环境 Posted by  makewonder on 2014 年 4 月 2 日   最近接触PAAS相关的知识,在研发过程中开始使用Docker搭建了自己完整的开发环境, ...

  2. 利用Docker构建开发环境

    最近接触PAAS相关的知识,在研发过程中开始使用Docker搭建了自己完整的开发环境,感觉生活在PAAS时代的程序员真是幸福,本文会简要介绍下Docker是什么,如何利用Docker来搭建自己的开发环 ...

  3. 使用 Vagrant 构建开发环境

    使用 Vagrant 构建开发环境 摘要:本文描述了如使用 Vagrant 构建统一的开发环境. 问题 作为开发人员,我们通常面临的问题有: 开发环境需要手工安装配置,这包括操作系统(CentOS.U ...

  4. (转)EOSIO开发(一)使用Docker构建本地环境

    前言 一直想学习EOS开发,但是不知道怎么入门.最近从GitHub上下载了源码,发现官方已经提供了完整的EOSIO开发入门教程,既然如此赶紧开始行动.今天是系列文章的第一篇,介绍如何使用Docker搭 ...

  5. Docker 搭建开发环境

    本文介绍如何将Docker集成到开发环境,自动构建应用,并使容器拥有独立的内网IP为开发人员提供服务. 术语解释 Docker镜像:一个不可修改的"模板",每个代码版本对应一个镜像 ...

  6. [Docker] 容器开发环境最佳实践理论

      保持 image 小       选择合适的 base image.       使用 multi-stage 构建. https://docs.docker.com/develop/develo ...

  7. 利用Docker搭建开发环境

    一. 前言 随着平台的不断壮大,项目的研发对于开发人员而言,对于外部各类环境的依赖逐渐增加,特别是针对基础服务的依赖.这些现象导致开 发人员常常是为了简单从而直接使用公有的基础组件进行协同开发,在出现 ...

  8. EOS Dapp开发(1)-基于Docker的开发环境搭建

    随着EOS主网的上线,相信基于EOS的Dapp开发会越来越多,查阅了很多资料相关的开发资料都不是很多,只能自己摸索,按照网上仅有的几篇教程,先git clonehttps://github.com/E ...

  9. 使用 docker 搭建开发环境

    作为一个 freelancer,经常能够接到很多的开发工作,这些金主,有喜欢 PHP 的,有习惯撒手不管的:有偏好 sqlite 的,也有喜欢 PG 的,我甚至见过 mysql.PG 一起使用的项目: ...

随机推荐

  1. C 输入输出函数

    流 就C程序而言,所有的I/O操作只是简单地从程序移入或移出字节的事情.这种字节流便称为流( stream ). 绝大多数流是完全缓存的,这意味着"读取"和"写入&quo ...

  2. python在指定一行的下一行插入文本

    给定一个程序,程序中有许多函数,比如,funcA,funcB,现在,如何在生成的函数中插入一个logger()语句? 这里用一个solidity程序做例子 pragma solidity ^0.4.0 ...

  3. TCP三次握手四次挥手,通俗易懂版

    三次握手四次挥手 三次握手 其实很好理解,三次握手就是保证双手都有发送和接受的能力.那么最少三次才能验证完成 即----> 客户端发送---服务端收到----服务端发送-- 1.客户端发送 -- ...

  4. 初始CSS01

    CSS基础知识 CSS介绍 CSS全称为层叠样式表,与HTML相辅相成,实现网页的排版布局与样式美化. 使用方式 根据样式表在页面中呈现的方式不同,可以通过以下三种方式在页面中使用格式 内联样式 改样 ...

  5. 【二食堂】Alpha - Scrum Meeting 7

    Scrum Meeting 7 例会时间:4.17 11:40 - 12:00 进度情况 组员 昨日进度 今日任务 李健 1. 继续文本区域的开发,先完成目前简陋的添加方式,再区实现勾选功能issue ...

  6. 第32篇-解析interfacevirtual字节码指令

    在前面介绍invokevirtual指令时,如果判断出ConstantPoolCacheEntry中的_indices字段的_f2属性的值为空,则认为调用的目标方法没有连接,也就是没有向Constan ...

  7. 零基础小白要如何跟好的学习嵌入式Linux(转)

    作为一个新人,怎样学习嵌入式Linux?被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学 ...

  8. 矩形覆盖 牛客网 剑指Offer

    矩形覆盖 牛客网 剑指Offer 题目描述 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形.请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? class Solution: ...

  9. 一步一步学ROP之linux_x86篇(蒸米spark)

    目录 一步一步学ROP之linux_x86篇(蒸米spark) 0x00 序 0x01 Control Flow Hijack 程序流劫持 0x02 Ret2libc – Bypass DEP 通过r ...

  10. cm0 逆向分析

    目录 cm0 逆向分析 前言 Strings工具复习 String工具使用说明 Strings工具解cm0题 cm0 逆向分析 前言 Emmmmm,我假装你看到这里已经学过了我的<恶意代码分析实 ...