docker构建前端工作环境

1,330 阅读12分钟

docker构建前端工作环境

docker安装

可以在docker官网 下载Docker Desktop 直接安装

如果是windows 的同学请注意,Docker Desktop只支持windows 专业版,一般我们自己的电脑都是Windows 家庭版,所以如果需要就安装 docker tool,当然也可以把自己的window系统升级到专业版,淘宝自己搜

安装完成运行以后我们会有一个docker小图标

docker 换源

类似npm,docker也有一个镜像管理器,为了方便我们以后的下载镜像,记得给docker换源

settings -> Docker Engine

{
  "registry-mirrors": [
    <!--地址网上找的-->
    "https://dockerhub.azk8s.cn",
    "https://hub-mirror.c.163.com"
  ],
  "insecure-registries": [],
  "debug": true,
  "experimental": false
}

docker基本概念

  • Image(镜像)
  • Container(容器)
  • Volume(卷)
  • 端口映射
  • dockerFile

对docker有了解的应该已经知道这些概念,如果不了解,先不必计较这些名词,稍后我们在使用中慢慢了解即可

docker 命令

docker image ls // 查看当前镜像列表 或者docker images 也可以
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] //拉取需要的镜像,tag代表版本号,不加默认是latest
docker image rm [选项] <镜像1> [<镜像2> ...]
docker run xxx(要使用的镜像名) // 运行容器
docker ps // 查看运行的容器
docker ps -a // 查看所有的容器
docker container rm // 删除容器
docker commit -m "描述信息" xxx(容器名) xxx:tag(生成的镜像名) // 把某个容器生成镜像

以上就是我平时最常用的命令了,当然,docker还有许多有用的命令,如果有需要,小伙伴们可以去官网了解更详细的内容,也可以阅读文末的参考资料

启动容器

docker image ls //镜像列表  如果之前没有用过docker,这个时候应该是没有镜像的

接下来获取我们需要的镜像

docker pull ubuntu  // 拉取镜像 不加版本号默认是最新的  如果需要版本 ubuntu:tag

等待下载完毕以后可以运行一下docker image ls,这个时候肯定有镜像了

我们可以看到,我们的镜像Ubuntu只有64.2MB 意味着这是一个非常轻量级的ubuntu系统

那么最关键的一步来了,运行容器

docker run ubuntu

你可能会发现命令行闪了几下一下,然后没有任何反应 我们可以通过

docker ps -a

或者是右键docker小图标,选中Dashboard 看到

说明我们的容器其实已经启动过了,只是就像你启动了一个空脚本,脚本已经跑了一遍了,没有任何交互,没有任何执行,运行就关闭了 那么接下来,我们就让容器跟我们产生一个交互,顺便给容器起个名字

docker run -it --name xxx ubuntu /bin/bash   // -it = -i(表示持续运行) -t(分配一个命令行用来交互) --name 命名   /bin/bash 指令,是用来规定你要使用哪种命令行交互,可以省略

这样是不是一切都好了起来呢,到这个时候,我们就正式用Ubuntu的镜像启动了一个容器,是不是觉得像通过命令行进入了一个Ubuntu虚拟机

每次启动的容器不能同名,不然会失败,可以通过docker 删除之前的容器或者加tag

如何退出和重新进入容器

先说退出,我们可以通过直接关闭命令行来退出,当然也可以输入

exit

那么我们如何重新进入容器呢

docker attach xxx (容器id)
// 或者
docker exec -it xxx(容器id) bash

另外我推荐通过我们的Docker Desktop,毕竟这个工具本来就是方便我们操作的

点击几下就可以进入容器了,可以看到Docker Desktop其实就是用exec命令 ,而且我们注意到后面的/bin/sh,如果你想切换成bash,只需要输入bash 回车即可

配置环境

好的,我们已经再次进入了我们的Ubuntu容器中接下来是一系列的安装环境操作

sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list // apt 换源
apt-get update

apt-get install vim bash-completion curl -y   // 添加vim 路径补全 curl
apt install node -y // node 版本8.10 我觉得够用了
apt install npm -y  // 安装npm 
npm config set registry https://registry.npm.taobao.org   // npm 换源
apt install nginx -y 

我们需要的环境依赖就安装完毕

如果我们什么都不做就退出容器,那么下次你会发现我们安装过的依赖全部没有了,因为我们每次启动容器都是依照我们镜像里的内容,而之前安装的所有东西不会影响我们的Ubuntu镜像内容,所以如果下载启动我们还是用Ubuntu这个镜像的话,之前安装的肯定是不存在的。这个时候就需要我们把我们安装好的各种依赖保存起来,重新生成一个镜像,下次再运行容器的时候就可以直接使用我们新生成的镜像。而不需要用Ubuntu镜像从头安装所有的依赖

生成我们的镜像

本地命令行执行:

docker commit -m "初始化完成" xxx(CONTAINER ID) xxx(要命名的镜像名)

可以看到,我们新生成的镜像比最初的Ubuntu镜像大了很多

这个时候,我们需要的镜像已经生成完毕,那我们如何跟我们的前端环境联系在一起呢 我们可不可以在刚才那个容器里面直接git clone 我们的项目到docker容器里面,然后再 commit 生成镜像,之后我们就可以在任意一台安装docker的电脑上下载我们的镜像,运行我们的容器,这个容器里已经安好了node npm 等各种前端环境依赖,甚至是我们的项目

但是有个问题,我如果想在docker上开发项目、运行是不是就很麻烦了,不能使用vscode来编写代码,不能用Google浏览器来浏览页面,那如何解决呢

解决的方法就是docker 的 Volume端口映射, 之前的操作我相信大家应该对 Image(镜像)Container(容器) 有所了解,那么接下来我们就说说Volume端口映射

Volume

先说 volume

volume 可以理解为一块区域,这块区域是宿主机的某个文件夹,某个文件,可以被本地读写,也可以被docker容器读写(但是docker容器也需要指定一个内部位置放置这个区域内容), 这样不就可以让本地和docker容器通过同一个volume 来共享一些内容了,比如说我们的项目,我们的一些配置文件. 那容器怎么知道哪个地方是可以共享的呢, 就要通过我们的命令来通知它了 ,这个操作就是我们说的挂载
(本地文件 (volume))
               ((volume) docker容器)

docker run -it -v xxxx(本地路径指定的共享目录):xxx(容器指定的挂载路径) --name xxx(名字) xxx(镜像) // -v 来定义要挂载的地方

我本地有一个vue项目,我将执行

docker run -it -v /e/code/vue/:/root/vue --name testVolumeTest demo:v1 /bin/bash

注意:我刚才生产的镜像是定义了tag 的,所以我不可以只写demo,因为只写demo镜像会找demo:latest

这个时候我们是不是就在本地和docker容器里面共享了我们的项目了,接下来该干嘛不用说了吧

容器里:

npm install
npm run dev

这个时候我们就可以再docker里运行我们的项目,但是运行起来以后我们该怎么在浏览器上查看我们的页面呢,这就要通过docker 的端口映射了

端口映射

现在我们就剩下最后一道门槛,如何用本地的谷歌浏览器访问docker里运行的项目

还记得我们安装的nginx吗?当时我们只是安装了nginx,并没有运行,现在我们来试试,该如何通过端口映射访问nginx

docker run -it -p 80(本地端口号):(本地端口号) --name portMapTest demo:v1 /bin/bash // -v 执行一个端口

前端应该好理解端口号映射吧

我们进入容器内部,启动nginx,看看有没有效果

好的,我们看到容器内部nginx已经启动,那么我们去本地浏览器看看是否能看到nginx的页面吧

没有任何问题,既然本地端口和docker容器端口可以映射,那我们在容器中运行的项目当然也可以在本地浏览器里面打开了,大部分前端项目都是8080端口,所以我们只要映射8080端口或者你自己的项目即可即可

扩展

之前,我们可以说已经能把项目成功的在docker容器中开发了,那么我们还有什么前端方面的环境可以再docker中使用呢

举个例子,nginx配置,很多公司或者个人有自己的nginx配置,那么我们是不是可以把自定义的nginx配置文件加载到docker容器的nginx中,可以直接写入,重新生成镜像,也可以在启动的时候挂载配置文件,这样是不是就不需要我们在自己的电脑上启动nginx,甚至还得添加一堆单独的配置文件,来回切换

再举个例子,hosts文件的修改,平时可能在开发中我们需要添加一些域名映射,是不是我们可以直接把hosts文件写入到docker镜像中呢,注意:这个还真不行,原因:docker每次启动容器的时候会动态更新容器的ip地址,为了防止hosts产生冗余,每次会重新写入hosts,所以你写入的hosts也会被重新覆盖

但是有一个小技巧可以帮我们写入hosts

优化

小技巧就是写一个初始化脚本,在docker容器启动的时候执行 首先我现在容器中写入一个myhosts文件,放入自己的hosts 当我们运行容器的时候,是可以带一个命令参数的

docker run -it name images xxxx(这里可以添加一些命令)

所以我们先在容器中创建一个init.sh

#!/bin/bash
<!--将myhosts的内容追加到hosts-->
cat /etc/myhosts >> /etc/hosts && ngnix 

记得要给权限

chmod -R 777 init.sh

保存容器为一个镜像images 命名为web

那么.我们最终的镜像就生成了

docker run -it -p 8080:8080 -v /e/code/nginx/nginx.conf:/etc/nginx/nginx.conf -v /e/code/vue:/root/vue  --name xxx web /bin/bash -c "./init.sh&&/bin/bash"

这样,在启动的时候我们就更改了hosts文件,还配置了自定义的nginx配置文件,然后启动了nginx

接下来就可以在容器中运行我们的项目了 我们在本地通过vsocde开发,浏览器调试,代码却运行在Ubuntu镜像里

上传

镜像是弄好了,但是得能给大家用,不然就没有意思了,所以还需要上传到docker仓库里

docker login  //登录

docker tag xxxxx(容器id) xxx(登录名)/xxx(镜像名):tag(版本自己写默认是latest) // 先修改镜像名 因为需要和别人做区分,所以你的镜像要加上你的docker账号名为前缀

docker push xxx/xxx // 上传仓库

这样我们的镜像就上传成功,我们在docker Hub登录自己的账号后就能看到自己上传的镜像了,当然,别人也可以使用我们封装好的镜像来开发运行了

如何使用

假设有同学新入职,从他入职到进入项目开发可以这样使用

  1. 领到新电脑

  2. 安装 docker /git

  3. git clone xxxxx

  4. docker pull 你的名字/镜像名 // 假设是zhangsan/web
    
  5. docker run -it -v 项目地址:/root/文件名 -v nginx.conf路径:/etc/nginx/nginx.conf -p 8080:8080
    --name 容器名 zhangsan/web /bin/bash -c "./init.sh&&/bin/bash"  // 这样就有了一个Ubuntu node npm nginx 的前端环境
    
  6. 开始开发

好处

  1. 新人入职简单,少了很多环境配置
  2. 所有人开发统一环境,不管你是mac windows,都是统一node,npm 版本 统一Ubuntu环境
  3. 所有配置都被封装到容器里面,本地不需要配置或者来回切换
  4. 跟线上服务器环境一致(假设线上也是ubuntu的话,如果不是就重新生成一个服务器版本的镜像)

参考资料

  • Docker — 从入门到实践 有纸质版和电子版,希望大家多多支持,我买的纸质版是第二版,现在已经有第三版了
  • 还参考了很多优秀的的博客和教程,不一一列举了,统一感谢

未完待续...

很多操作还没讲,比如删除容器,删除镜像,不过这些大家去官网熟悉熟悉命令就明白了,我觉得还剩下两个大点:一个是dockerFile 没有讲,dockerFile 可以理解为把命令行里面的各种操作写成一个配置文件,通过配置文件来生成一个新的镜像,或者启动一个新的容器,大家可以自己看看,试着写写就好
第二个就是docker在微服务的应用(前端方面),docker入门很简单,你就把它当成一个虚拟机就好,难点在于多容器如何配合通信,多台服务器里面的多个容器如何统一通信,其中涉及了很多通信机制,网管配置,还有docker compose,k8s等等,我自己也要学习学习,积累积累,以后有机会再总结总结