在下最近遇到要在服务器上安装 Mysql、Nginx、EasyMock 等工具的场景,这里记录一下我使用 Docker 安装的过程,但愿也能在相似的场景中帮助到你们~ html
本文前备知识须要一些 Linux 的一些基本命令,推介先看一下 <半小时搞会 CentOS 入门必备基础知识> 这篇文章。前端
CentOS 版本: 7.6
mysql
Nginx 版本: 1.16.1
linux
Docker 版本: 19.03.12
nginx
你多学同样本事,就少说一句求人的话
先后端开发到测试到生产的过程当中,常常会遇到一个问题,明明我在本地跑没问题,为何到测试环境或者生产环境就报错了了呢,经常这是由于开发、测试、生产的环境与配置不一样致使的。git
折腾过环境配置的人都明白其中麻烦,换一台系统、虚拟机、机器,就又要重来一次,费力费时。因为环境和配置的缘由,各类奇奇怪怪由于环境和配置的 Bug,老是像打地鼠游戏里面的地鼠同样不断冒出来 🐹github
Docker 对这个问题给出了一个很好的解决方案,经过镜像将除了系统以外所须要的系统环境由下而上打包,达到服务跨平台的无缝运做。也就是说,安装的时候,把特定的环境如出一辙地搬过来,从而解决「在个人电脑上能跑,在 xx 环境就跑不了」的状况。web
另一个重要的缘由,就是轻量,基于容器的虚拟化,Docker 的镜像仅包含业务运行所需的 runtime 环境,一个 CentOS/Ubuntu 基础镜像仅 170M,由于轻量一个宿主机能够轻松安装数百个容器。redis
Docker 是基于 Go 语言实现的云开源项目,从 2013 年发布到如今一直广受关注。Docker 可让你像使用集装箱同样快速的组合成应用,而且能够像运输标准集装箱同样,尽量的屏蔽代码层面的差别。它将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。sql
程序在这个虚拟容器里运行,就好像在真实的物理机上运行同样。有了 Docker,就不用担忧环境问题。
本文就不对比虚拟机跟 Docker 的区别和优劣了,每一个文章都有,说烂了,想了解的话能够百度一下 😂,我这里就很少说了,下面直接看看怎么安装怎么用起来吧。
在下直接使用 Homebrew Cask 来安装,Mac 下:
# Homebrew 安装 $ braw cask install docker
便可,安装完输入命令,直接报错!
➜ ~ docker zsh: command not found: docker # 报错
遇到这个报错别担忧,安装完以后要在应用列表里面双击 Docker 应用,输入密码以后就可使用这个命令了 😅。
Docker 要求 CentOS 版本必须在 6.5 及以上才能够安装。
# 安装 $ sudo yum install yum-utils device-mapper-persistent-data lvm2 $ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo $ sudo yum install docker-ce # 开启 Docker $ sudo systemctl start docker
在 Windows 上能够直接下载安装包来安装,或者 Mac 上不使用 Homebrew 也能够去官网直接下载安装包来安装,百度一下处处都是安装方法,其余的就不用多说。
在 MacOS 的 Docker 配置 Perferences -> Docker Engine
或者 Windows 的 Settings -> Deamon
中的 JSON 中增长一项 registry-mirrors
以下
配置完以后在命令行中 docker info
就能够查看到咱们配置的镜像加速地址了。
➜ ~ sudo docker info ... Registry Mirrors: https://reg-mirror.qiniu.com/ http://hub-mirror.c.163.com/ https://registry.docker-cn.com/ ...
若是你的系统的 Docker 没有客户端,好比 CentOS 中,能够直接修改 deamon 配置文件:
# 修改/建立 docker 的 deamon 配置文件 $ sudo vi /etc/docker/daemon.json # 修改成以下配置 { "experimental": false, "debug": true, "registry-mirrors": [ "https://reg-mirror.qiniu.com", "http://hub-mirror.c.163.com", "https://registry.docker-cn.com" ] } # 修改完 :wq 重启 $ sudo systemctl restart docker
而后就能够快乐跑起来咱们第一个 Docker 指令 Hello World 了
Good start ! 🎉
镜像和容器的关系就像类和类的实例,一个镜像能够同时跑多个容器,单个容器实例又能够建立新的镜像。以下图:
下面解释一下这个图里面出现的元素
概念 | 说明 |
---|---|
Docker 镜像 Images | 用于建立 Docker 容器的只读模板,好比 Ubuntu 16.04系统、Nginx 1.16.0 等,是一个特殊的文件系统,包括容器运行时须要的程序、库、资源、参数等,但不包含任何动态数据,内容在构建后也不会被改变,一个镜像能够建立多个容器 |
Docker 容器 Container | 容器是独立运行、相互隔离的一个或一组应用,是镜像建立的运行实例,实质是进程,能够看做为一个简易版的 Linux 环境 + 运行在其中的应用程序 |
Docker 客户端 Client | 客户端经过命令行或者其余工具使用 Docker SDK (https://docs.docker.com/devel... 与 Docker 的守护进程通讯 |
Docker 主机 Host | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器 |
Docker 仓库 Repository | 集中存放镜像文件的地方,分为公有仓库和私有仓库。 |
Docker 注册服务器 Registry | 是一个集中存储、分发镜像的服务,官方的叫 Docker Hub。一个 Docker Registry 中可包含多个仓库,每一个仓库能够包含多个标签 Tag 的镜像,不一样的标签对应不一样的版本 |
Docker Machine | Docker Machine 是一个简化 Docker 安装的命令行工具,经过一个简单的命令行便可在相应的平台上安装Docker,好比 VirtualBox、 Digital Ocean、Microsoft Azure |
容器的生命周期图示
容器的五个核心状态,也就是图中色块表示的:Created、Running、Paused、Stopped、Deleted:
本文主要关注于使用,就不太赘述这些状态的切换等,下面直接上手。
# 开启 Docker 开机自启动 $ sudo systemctl enable docker # 关闭 Docker 开机自启动 $ sudo systemctl disable docker
# 去下载镜像,先从本地找,没有去镜像,最后没有去 hub,标签不写默认为 lastest $ docker pull [镜像名]:[标签Tag] # 列出本机的全部 image 文件,-a 显示本地全部镜像(包括中间镜像),-q 只显示镜像ID,--digests 显示镜像的摘要信息 $ docker image ls $ docker images # 删除 image 文件, -f 强制删除镜像 $ docker rmi [镜像名][:标签Tag] $ docker rmi [镜像名1][:标签Tag] [镜像名2][:标签Tag] # 删多个 $ docker rmi $(docker ps -a -q) # 删所有,后面是子命令 # 查询镜像名称,--no-trunc 显示完整的镜像描述,--filter=stars=30 列出star很多于指定值的镜像,--filter=is-automated=true 列出自动构建类型的镜像 $ docker search [关键字] # 下载镜像,标签 tag 不写默认为 lastest,也能够本身加好比 :3.2.0 $ docker pull [镜像名][:标签Tag]
# 列出本机正在运行的容器,-a 列出本机全部容器包括终止运行的容器,-q 静默模式只显示容器编号,-l 显示最近建立的容器 $ docker container ls # 等价于下面这个命令 $ docker ps # 新建并启动容器 $ docker run [option] [容器名] # 启动容器 $ docker start [容器ID]/[容器Names] # 重启容器 $ docker restart [容器ID]/[容器Names] # 终止容器运行 $ docker kill [容器ID] # 强行终止,至关于向容器里面的主进程发出 SIGKILL 信号,那些正在进行中的操做会所有丢失 $ docker kill $(docker ps -a -q) # 强行终止全部容器 $ docker stop [容器ID] # 从容终止,至关于向容器里面的主进程发出 SIGTERM 信号,而后过一段时间再发出 SIGKILL 信号 $ docker stop $(docker ps -a -q) # 终止全部容器 # 终止运行的容器文件,依然会占据硬盘空间,可使用 docker container rm 命令删除,-f 强制删除能够删除正在运行的容器 $ docker rm [容器ID] $ docker rm `docker ps -aq` # 删除全部已经中止的容器,由于没中止的rm删不了须要加-f # 查看容器的输出,-t加入时间戳,-f跟随最新日志打印,--tail数字显示最后多少条,若是docker run时,没有使用-it,就要用这个命令查看输出 $ docker logs [容器ID] # 查看容器进程信息 $ docker top [容器ID]/[容器Names] $ docker port [容器ID]/[容器Names] # 退出容器 $ exit # 容器退出 ctrl + p + q # 容器退出,快捷键 # 进入容器 $ docker attach [容器ID] # 退出容器时会让容器中止,本机的输入直接输到容器中 $ docker exec -it [容器ID] # 退出容器时不会让容器中止,在已运行的容器中执行命令,不建立和启动新的容器 # 设置容器在docker启动时自动启动 $ docker container update --restart=always [容器名字]
这里要特别说一下 docker run
的 option
,由于最经常使用:
--name
为容器指定一个名称;-d
容器启动后进入后台,并返回容器 ID,即启动守护式容器;-P
随机端口映射;-p 80:8080
将本地 80 端口映射到容器的 8080 端口;bash
容器启动之后,内部第一个执行的命令。这里启动 bash,保证用户可使用 Shell;-i
以交互模式运行容器,一般与 -t
同时使用;-t
为容器从新分配一个伪输入终端,容器的 Shell 会映射到当前的 Shell,而后在本机窗口输入的命令,就会传入容器,一般与 -i
同时使用;--rm
在容器终止运行后自动删除容器文件;--restart=always
设置容器自启动;-v /xxx:/yyy
映射命令,把本机的 xxx 目录映射到容器中的 yyy 目录,也就是说改变本机的 xxx 目录下的内容, 容器 yyy 目录中的内容也会改变;好比我在 CentOS 下跑起来一个 CentOS 的 Docker 容器:
# 下载 $ docker pull centos # 在上面下载的 centos 镜像基础上,新建一个容器名为 mycentos0901 的 centos 实例,并进入这个容器的 bash $ docker run -it --name mycentos0901 0d120b6ccaa8 [root@169c9fffeecd /] # 进入容器,下面输入命令,注意这里 root 后面的一串 ID $ ls # 能够看到centos的根目录文件列表 $ docker # bash: docker: command not found 这个容器没有安装docker
是否是很神奇,咱们能够在一开始的 CentOS 下面执行 docker ps
来查看容器列表:
你会发现上面那个 ID,正是下面列表中跑起来的这个容器的 ID,镜像的 ID 也是咱们前面 pull
下来的 CentOS 镜像 ID,名字也是咱们起的 mycentos0901
。
若是 docker run
以后报 Conflict. The container name "xxxx" is already in use by container
就直接运行 docker rm $(docker ps -a -q)
删除已中止的容器,或者精确删除 docker rm [containerID]
也能够,就能够了。
使用 centos
之后台模式启动一个容器 docker run -d --name mycentos0903 0d120b6ccaa8
,启动以后 docker ps -a
查看,发现容器并不在运行中,这是由于 Docker 的运行机制:Docker 容器后台运行,必须有一个前台进程。
容器运行的命令若是不是那些一直挂起的命令,好比 top
、tail
,运行结束会自动退出。因此为了让容器持续在后台运行,那么须要将运行的程序之前台进程的形式运行。
好比这里在后台运行一个命令,这个命令一直在打印 docker run -d centos /bin/sh -c "while true; do echo hello zzyy; sleep 2; done"
,而后咱们 logs
查看一下:
退出容器后能够经过 exec
方法对正在运行的容器进行操做:
拷贝文件使用 cp
命令
$ docker cp [容器ID]/[容器Names]:[要拷贝的文件目录] [本机目录] # 容器文件拷贝到本机 $ docker cp [本机目录] [容器ID]/[容器Names]:[要拷贝的文件目录] # 本机文件拷贝到容器
cp
不只能把容器中的文件/文件夹拷贝到本机,也能够把本机中的文件/文件夹拷贝到容器。
演示一下,这里先到容器里面建立一个无聊的文件 xixi.txt
,而后拷贝到本机:
实用的时候,咱们能够拷贝配置、日志等文件到本地。
# 查询镜像 $ docker search mysql # 下载镜像,实测没配置镜像加速的时候会比较慢,配置了就好一些 $ docker pull mysql # 查看镜像 $ docker images # 建立并运行容器 $ docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=888888 -v /Users/sherlocked93/Personal/configs/mysql.d:/etc/mysql/conf.d --name localhost-mysql mysql
稍微解释一下上面的参数:
-p 3307:3306
将本机的 3307 端口映射到 mysql 容器的 3306 端口,根据须要自行更改;-e MYSQL_ROOT_PASSWORD=<string>
设置远程登陆的 root 用户密码;--name <string>
可选,设置容器别名;-v xxx/mysql.d:/etc/mysql/conf.d
将本地目录下设置文件夹映射到容器的 /etc/mysql/conf.d
-v xxx/logs:/logs
将本机指定目录下的 logs
目录挂载到容器的 /logs
-v xxx/data:/var/lib/mysql
将主机制定目录下的 data
目录挂载到容器的 /var/lib/mysql
运行截图:
而后去 Navicat 中就能够链接到 MySQL 了。
这也太爽了!真的是几行命令就装好了啊,比以前真是快乐多了 😂
Nginx 的安装和其余的相似,若是你还不太了解 Nginx 如何使用,能够参看 <Nginx 从入门到实践,万字详解> 这篇文章,看完基本就了解如何使用和配置了。
# 查询/下载镜像 $ docker search nginx $ docker pull nginx
而后建立一个临时的容器,目的是把默认配置拷贝到本机,我这里把配置文件放到 /mnt
目录下,主要是三个配置文件夹:
/etc/nginx
放置 Nginx 配置文件;/var/log/nginx/
放置 Nginx 日志文件;/usr/share/nginx/html/
放置 Nginx 前端静态文件都放在这个文件夹;分别把这几个目录都拷贝到本机的 /mnt
文件夹下的 nginx
、nginx_logs
、html
文件夹。
刚刚建立的临时容器没用了 docker rm -f [临时容器ID]
把临时容器干掉,而后 docker run
从新建立 Nginx 容器:
$ docker run -d --name localhost-nginx -p 8082:80 \ -v /mnt/nginx:/etc/nginx \ -v /mnt/nginx_logs:/var/log/nginx \ -v /mnt/html:/usr/share/nginx/html \ --privileged=true nginx
--privileged=true
表示容器内部对挂载的目录拥有读写等特权。
其余配置刚刚上面以前已经讲过,应该不用讲了。
而后在你本身浏览器上就能够访问了,若是是云服务器,记得开放对应端口。
由于 Easy Mock 依赖 Redis 和 MongoDB,所以本地环境使用 docker-compose 来搭建 Easy Mock 应该算是最佳实践了。
官方文档: https://docs.docker.com/compose/install/
首先你得肯定拥有 docker 环境,若是你是 Windows / Mac 用户,那么安装客户端,就会自带 docker-compose 了。
由于本次咱们是在云服务器 CentOS7.6 上搭建,因此咱们须要自行安装 docker-compose,运行以下命令,下载当前稳定版本的 docker-compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
修改文件权限为可执行文件
$ sudo chmod +x /usr/local/bin/docker-compose
验证是否安装成功
$ docker-compose version
能够参考官方文档给出的部署文档,也能够参考我下面的配置过程。
首先新建文件 docker-compose.yml
并将下面 docker-compose 文件内容复制进入 docker-compose.yml
,而后将内容中注释位置替换为本身须要的本地地址
version: '3' services: mongodb: image: mongo:3.4.1 volumes: # /apps/easy-mock/data/db 是数据库文件存放地址,根据须要修改成本地地址 - '/apps/easy-mock/data/db:/data/db' networks: - easy-mock restart: always redis: image: redis:4.0.6 command: redis-server --appendonly yes volumes: # /apps/easy-mock/data/redis 是 redis 数据文件存放地址,根据须要修改成本地地址 - '/apps/easy-mock/data/redis:/data' networks: - easy-mock restart: always web: image: easymock/easymock:1.6.0 # easy-mock 官方给出的文件,这里是 npm start,这里修改成 npm run dev command: /bin/bash -c "npm run dev:server" ports: - 7300:7300 # 改成你本身指望的映射 volumes: # 日志地址,根据须要修改成本地地址 - '/apps/easy-mock/logs:/home/easy-mock/easy-mock/logs' networks: - easy-mock restart: always networks: easy-mock:
在 docker-compose 文件目录下,运行以下命令:
$ docker-compose up -d
若是遇到 easymock docker 实例报文件权限错误
Error: EACCES: permission denied....
要在项目根目录执行如下命令
$ chmod 777 /yourfile/logs
而后就能够经过浏览器上的 你的域名.com:7300
访问到 easy-mock 了!
若是你以为域名后面跟着端口号挺难看的,你能够经过配置 Nginx 的二级域名来访问你部署的 easy-mock,配置二级域名的方法参见 这篇文章
关于可视化查询工具,这里就简单推介一个 LazyDocker,因为是在终端运行的,并且支持键盘操做和鼠标点击,就挺骚气的,有了这个一些查询语句能够少打几回了。
安装比较简单,运行下面的命令:
$ docker run --rm -it -v \ /var/run/docker.sock:/var/run/docker.sock \ -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker \ lazyteam/lazydocker
能够设置一个终端的 alias
$ alias lzd='docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker lazyteam/lazydocker'
而后你在终端输入 lzd
就能够浏览你的镜像、容器、日志、配置、状态等等内容了。
因为在下目前使用 Docker 的主要场景是 MySQL、Nginx 之类工具的安装,因此本文所介绍的内容也大多属于这个场景。
篇幅缘由 Docker 还有一些内容本文没有介绍,但上面的内容已基本知足平常的使用,其余 Docker 的内容能够关注一下在下的后续文章~
网上的帖子大多深浅不一,甚至有些先后矛盾,在下的文章都是学习过程当中的总结,若是发现错误,欢迎留言指出~
参考文档:
做者其余高赞文章:
PS:本人博客地址 Github - SHERlocked93/blog,也欢迎你们关注个人公众号【前端下午茶】,一块儿加油吧~