经常写程序的同学们往往会遇到这样一些痛点:代码更新发布、部署效率实在是低下,环境的一致性也难以保证,明明在开发环境里能运行的代码,换了一台机器怎么就跑不通了?
云计算时代,还在用传统方式部署代码,怎么好意思说自己是9102年的工程师?实在是不能忍!今天,你虾就给大家安利一下被誉为“云计算时代的颠覆性技术”——Docker
什么是Docker?
Docker 是一个基于 Go 语言,并遵从 Apache2.0 协议开源的应用容器引擎。
它是一种容器级的虚拟化技术, 开发者可以打包他们的应用以及依赖包到一个轻量级、可移植的容器中,并发布到任何流行的 Linux 机器上,无需担心环境的问题。
docker
Docker 和 VM,傻傻分不清楚
前面我们提到,Docker 是一种基于虚拟化的技术,谈到虚拟化就不得不说 VM(Virtual Machine 虚拟机),既然都是基于虚拟化,Docker 和 VM 又有什么差别呢,别急,咱们慢慢来聊这个问题。
我们先来看右侧 VM 的架构图,在 Infrastucture(可以理解为底层硬件)之上,有一层 Hypervisor,它是一种运行在物理服务器和操作系统之间的中间层,可以允许多个操作系统和应用共享底层硬件。虚拟机在主操作系统之上运行多个不同的子操作系统,并通过 Hypervisor 调用底层的硬件。
假设你需要运行3种相互隔离的应用,那你得创建3台虚拟机,这也就意味着在 Hypervisor 之上会运行着3个子操作系统,这样会产生特别大的资源开销。
(P.S 其实图中 Hypervisor 之上应该还有一层 Host Operating System)
Docker VS 虚拟机而 Docker 就显得十分轻便了,它的守护进程(Docker Daemon)取代了 Hypervisor,直接运行在操作系统之上,应用的源代码与它的依赖都打包在Docker镜像 (image) 中,Docker 引擎通过镜像去创建容器(container)。不同的应用运行在不同的容器中,它们之间是相互隔离的。
并且,Docker 守护进程可以直接与操作系统进行通信,为各个 Docker 容器分配资源,由于没有臃肿的从操作系统,虚拟机启动需要数分钟,而 Docker 容器可以在数毫秒内启动,效率提升明显,且节省了大量的磁盘空间以及其他系统资源。
说了这么多,你是不是认为 Docker 完全可以吊打虚拟机了呢,其实不是。俗话说术业有专攻,相比 Docker,虚拟机更擅长彻底隔离整个运行环境,最常见的就是云厂商通过VM的方式来隔离不同的用户;而 Docker 通常用于隔离不同的应用。
如何使用Docker
Docker的安装(以CentOS 7 为例)
#安装一些必要的系统工具:
yum install -y yum-utils device-mapper-persistent-data lvm2
#更新系统内核以及yum缓存
yum update
yum makecache fast
#安装Docker并启动
yum -y install docker-ce
systemctl start docker
#测试Docker是否安装成功
docker run hello-world
如果屏幕出现了 Hello from Docker ,恭喜你,安装这一步就已经大功告成了
Docker的相关概念
在进一步学习 Docker 之前,我们需要科普一些 Docker 的相关概念,这样在下面的学习中,你才会有一种事半功倍的 feeling
Key | Value |
---|---|
Docker镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板 |
Docker容器 (Container) | Docker通过镜像创建出容器,用于运行一组独立的应用 |
Docker仓库 (Registry) | 用于保存镜像的代码仓库 |
通常,我们会从Docker仓库中下载对应的镜像,并通过镜像创建出运行应用的容器
Docker实例
多说无益,下面我们将通过两个比较典型的实例,将相关的知识点串联起来,来学习如何使用Docker
使用Docker安装Python
刚刚我们说过,想使用Docker容器,第一步是从仓库中下载相应的镜像,这就引出了我们教程中的第一条命令
docker search
作用:从镜像仓库中查找指定镜像
语法:docker search [OPTIONS] TERM
示例:docker search python
详解:从仓库中寻找Python相关的镜像
[root@FUCC ~]# docker search python
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/python Python is an interpreted, interactive, obj... 4356 [OK]
docker.io docker.io/django Django is a free web application framework... 856 [OK]
docker.io docker.io/pypy PyPy is a fast, compliant alternative impl... 196 [OK]
docker.io docker.io/kaggle/python Docker image for Python scripts run on Kaggle 125 [OK]
docker.io docker.io/arm32v7/python Python is an interpreted, interactive, obj... 38
docker.io docker.io/centos/python-35-centos7 Platform for building and running Python 3... 36
在这里我们直接选择官方的镜像,标签(版本)为3.7
docker pull
作用:从镜像仓库中拉取或者更新指定镜像
语法:docker pull [OPTIONS] NAME:TAG
示例:docker pull python:3.7
详解:从仓库中下载标签为3.7的 Python镜像
[root@FUCC ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...
3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============> ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================> ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==> ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7
此时,Docker便已经帮我们从仓库中下载指定的镜像了,下载完成后,可以使用下面这条命令来查看本地已经存在的Docker镜像
docker images
作用:列出本地镜像
语法:docker images [OPTIONS] [REPOSITORY[:TAG]]
示例:docker images
详解:查看本地所有的docker镜像
[root@FUCC ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/python 3.7 42d620af35be 6 days ago 918 MB
docker.io/rabbitmq 3-management 7aae48fa6ef6 7 days ago 179 MB
docker.io/golang latest f50db16df5da 9 days ago 774 MB
可以看到,此时本地已经存在了python3.7的镜像,事不宜迟,我们就用这个镜像来创建一个容器吧,Let's go !
docker run
在创建容器之前,我们先简单聊一下ID的概念,在Docker中,我们通常使用ID来作为一个镜像或者容器的唯一标识,一般以"命令 + ID"的方式对一个镜像或者容器进行操作,如上面这段代码,我们可以看到python3.7这个镜像的ID为42d620af35be
作用:创建一个新的容器
语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
为了测试我们的python环境是否安装完成,我们先在本地新建一个 hello.py 的文件
##!/usr/bin/python
import sys
print("Hello, Docker!")
print(sys.version) #输出Python版本号
以我的环境为例,我把这段代码保存在了本地的 /root/code/python 目录下
接下来,我们就使用 docker 中的 python 环境去运行这段代码吧
[root@FUCC python]# docker run -v $PWD:/usr/src/code -w /usr/src/code python:3.7 python hello.py
Hello,Docker!
3.7.4 (default, Jul 13 2019, 14:04:11)
[GCC 8.3.0]
乍一看,这么长的一段命令着实有点吓人,别慌,待我来把命令拆解开细细讲给你听
docker run: 用于创建一个容器,这段我们刚刚聊过,pass
-v $PWD:/usr/src/code: 用于挂载本地的目录到docker容器中,以这条命令为例,它将执行这段命令所在的目录,挂载到了容器中的 /usr/src/code 目录下,冒号前面是本地路径,后面为对应的容器中的目录,你也可以不用PWD,直接用绝对路径的写法
-w /usr/src/code: -w用于指定容器的工作目录,在上一步中,我们将本地存放python代码的目录挂载到了容器中的 /usr/src/code 目录,所以我们将这个目录设置为容器的工作目录
python:3.7:指定镜像,你也可以用Image ID 来替换这里的镜像名称
python hello.py:这里应该就不用我多说了,这是在容器中执行的命令
看到这里,我给你布置一道思考题,假设我在本地的 /root/data/ 目录中存放了一个 hello.go 的代码文件,想要使用Image ID 为 f50db16df5da 的golang 容器运行这段代码,命令应该怎么写呢,欢迎在评论区留言
(P.S 运行go语言代码的命令为 go run FILENAME)
使用Docker安装MariaDB
从Docker仓库中搜索并下载MariaDB镜像的过程相信你已经能无师自通了,这里我们主要是聊启动的过程。
相信你已经知道,类似于数据库这类的服务,需要在本地开启相对应的端口,那么在Docker中应该如何实现呢,还记得在刚刚的Python案例中,我们将存放代码的本地目录和容器中的目录做了一个映射吗,同样的,端口也可以有这种操作
[root@FUCC python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --restart unless-stopped 3a2ef06682ac
-d:将容器在后台运行
-p 3306:3306:将容器中3306的端口映射到主机的3306端口
-e MYSQL_ROOT_PASSWORD=123456:初始化root的密码为123456
--restart unless-stopped: 设置当容器意外停止时自动重启
3a2ef06682ac:创建容器的Image ID
这时我们可以验证一下数据库服务是否启动
docker ps
作用:列出容器
语法:docker ps [OPTIONS]
[root@FUCC ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
107b52416c13 3a2ef06682ac "docker-entrypoint..." 5 minutes ago Up 5 minutes 0.0.0.0:3306->3306/tcp quizzical_mcnulty
接下来,我们进入容器内部看一看
docker exec
作用:在运行的容器中执行命令
语法:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
示例:docke exec -it 107b52416c13 bash
详解:进入ID为107b52416c13的容器中执行bash命令
进入容器中,我们和平时操作Linux没什么两样,使用之前创建好的账户进入MariaDB,成功!
[root@FUCC ~]# docker exec -it 107b52416c13 bash
root@107b52416c13:/# mysql -u root -p123456
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
讲到这里,相信你对Docker已经有了一些简单的认识,但这些都只是沧海一粟,单靠这篇文章是绝对讲不完的(你标题不是说入门看这一篇就够了吗),在下一篇文章里(如果有的话),咱们再好好聊一聊进阶的内容,Bye~
网友评论