Bootstrap

linux docker虚拟,Docker虚拟化管理:30分钟教你学会用Docker

原标题:Docker虚拟化管理:30分钟教你学会用Docker

关于Docker的官方介绍网上太多了我就不贴了,就实际体验来说 Docker可以极大的简化环境搭建及服务部署的操作流程,大大降低部署的时间成本,解放你的双手。

本文不会深入讲解Docker底层架构及运行原理,也不会有一堆架构图贴在这里。该篇旨在让你以最快的速度学会使用Docker,关于Docker的架构及其底层的一些知识,你可以在学会Docker的基本使用之后再去了解。开门见山讲架构聊底层有点容易让人犯迷糊,但在使用Docker之前你至少应该了解他的三大核心组件:仓库、镜像和容器,以及他们之前的关系。本文将通过一个MySQL示例带你了解并使用Docker,待你对Docker有一个基本了解后你再回头去看他的体系架构会容易理解。

三大核心组件

仓库:仓库是集中存储镜像的地方,我们本地安装Docker之后,需要从仓库中拉取镜像。可以类比于Maven,有公有仓库和私有仓库之分。

镜像:是一个Linux的文件系统,它里面存放着可以再Linux内核中运行的程序及其数据。

容器:是镜像创建的运行实例,可以把它理解为一个精简版的Linux系统,里面运行着镜像里的程序。

为了更好的让你理解这三者的关系,我打一个不恰当但很形象的比方, 镜像就相当于你weixin.exe文件,容器相当于你安装好的微信程序,微信程序(容器)需要你的weixin.exe文件(镜像)来安装(创建),那么仓库就相当于应用商店了,你可以从商店下载你要的.exe文件(镜像)。

微信程序安装完成后你可以选择运行或者关闭,Docker容器一样可以运行和停止,微信程序你可以从系统卸载,Docker容器你同样可以选择删除。

但有一点不同的地方是,weixin.exe文件安装完成你就可以删除了,它和你的微信程序并没有关系,删掉安装文件不影响你微信程序的运行。但是镜像不同,如果有容器正在使用这个镜像,那么这个镜像是不能删除的(删除时会报Error不让你删)。

首发地址:https://www.guitu18.com/post/2020/01/20/66.html

安装Docker

CentOS安装Docker要求:

必须是64位操作系统

内核版本在3.8以上

你可以通过 uname -r 查看你的系统内核:

[root@localhost ~]# uname -r

3.10.0-1062.18.1.el7.x86_64

[root@localhost ~]#

yum方式安装:

yum install docker -y

安装完成你可以通过 docker version 查看你的docker版本信息:

[root@localhost ~]# docker version

Client:

Version: 1.13.1

API version: 1.26

Package version: docker-1.13.1-109.gitcccb291.el7.centos.x86_64

Go version: go1.10.3

Git commit: cccb291/1.13.1

Built: Tue Mar 3 17:21:24 2020

OS/Arch: linux/amd64

Server:

Version: 1.13.1

API version: 1.26 (minimum version 1.12)

Package version: docker-1.13.1-109.gitcccb291.el7.centos.x86_64

Go version: go1.10.3

Git commit: cccb291/1.13.1

Built: Tue Mar 3 17:21:24 2020

OS/Arch: linux/amd64

Experimental: false

[root@localhost ~]#

看到如上的信息说明你的Docker安装成功,你可以用 docker info 命令查看更详细的信息。

配置镜像加速

为了更愉快的使用Docker你可能还需要配置镜像加速,可以类比于Maven的私服,使用国内的镜像仓库能让你更快的拉取镜像。

执行 vim /etc/docker/daemon.json ,修改为如下配置:

{

"registry-mirrors":[

"https://reg-mirror.qiniu.com/",

"https://hub-mirror.c.163.com/"

]

}

重新加载配置及重启Docker服务:

systemctl daemon-reload

systemctl restart docker

执行 docker info 你可以看到镜像仓库配置已经生效了。

拉取镜像

Docker安装和配置都搞定了,现在你要从苍鹭下载镜像了,这里以 MySQL 5.7 为例:

#5.7为版本号,你也可以安装其他版本

docker pull mysql:5.7

46eb839f98abd417dbc0b9e7ad6577c2.png

拉取成功后通过 docker images 命令查看本地镜像:

[root@localhost ~]# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

docker.io/mysql 5.7 f965319e89de 3 hours ago 448 MB

[root@localhost ~]#

创建容器

有了镜像,你需要用它创建一个容器才能运行,创建并运行MySQL容器:

docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

执行成功后会返回容器ID,查看已创建的容器: docker ps -a

[root@localhost ~]# docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

8e1cd060075db23c61cb31cecb3a3321df92cf56ea7086476cc21e8709382d19

[root@localhost ~]# docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

8e1cd060075d mysql:5.7 "docker-entrypoint..." 3 seconds ago Up 1 second 0.0.0.0:3306->3306/tcp, 33060/tcp mysql

[root@localhost ~]#

可以看到刚才创建的MySQL容器已经在运行了,现在你可以通过 ${IP}:3306 连接MySQL数据库了(记得放行端口或者关闭防火墙)。

挂载目录

通过上面的步骤,你已经通过Docker运行起你的第一个容器MySQL了,而且你也能通过宿主机的端口连接到容器中的MySQL。但这样做还不是很安全,关于这个我们要先简单了解一下容器和宿主机之间的关系。

容器内和宿主机的文件系统是独立的(虽然整个容器也是以文件的形式存放在宿主机的某个目录上的),包括他们之间的网络,也是独立的。刚才运行的MySQL容器有一个 -p 3306:3306 的参数,这个参数就是映射宿主机和容器之间的端口的,你也可以配置成比如 -p 1234:3306 ,这样你通过访问宿主机的1234端口就能访问到容器的3306端口。

那么再回到文件系统,容器本身也是一个精简版的Linux系统,只不过他运行在宿主机上依赖于宿主机的硬件。容器内部也是有着一套独立的文件系统的,且 随着容器的删除,所有存在于容器内的所有文件都将被清除。刚才我们创建的那个MySQL容器,只要我们删除容器,数据库里的所有数据都将清除,这显然不是我们想看到的。

Docker的 run 命令提供了一个 -v 的参数,允许我们容器内部目录挂载为宿主机的本地目录,这样容器内的程序在操作这个目录时,其实操作的是宿主机的目录。那么 我们可以把程序运行的关键数据挂载到宿主机上的目录,比如MySQL的数据库文件,程序运行的日志文件等等。这样一来当我们在删除容器时,因为这些目录是存在于宿主机的,所以不会随着容器一起删除,从而实现了容器数据的持久化。

还是以刚才的MySQL容器为例,我们先删掉刚才的容器:

#mysql为容器名称,也可以是容器ID,通过 docker ps -a 查看容器信息

docker stop mysql

docker rm mysql

接着用下面的命令创建并运行MySQL容器,增加了一个 -v 参数:

#在宿主机创建挂载目录

mkdir -p /usr/local/mysql/conf

mkdir -p /usr/local/mysql/logs

mkdir -p /usr/local/mysql/data

#创建并运行容器

docker run -p 3306:3306 --name mysql

-v /usr/local/mysql/conf:/etc/mysql

-v /usr/local/mysql/logs:/var/log/mysql

-v /usr/local/mysql/data:/var/lib/mysql

-e MYSQL_ROOT_PASSWORD=123456

-d mysql:5.7

-v /usr/local/mysql/data:/var/lib/mysql

表示将宿主机的 /usr/local/mysql/data 目录挂载到容器内的 /var/lib/mysql 目录,那么容器内的MySQL程序操作的数据实际上是写入了宿主机的 /usr/local/mysql/data 目录了,其他两项同理。

这里挂载的三个目录分别为数据库运行的配置、日志和数据,也是MySQL程序最重要的数据,即便这个容器删除了,只要这些数据还在,我们就能通过重新创建容器恢复全部数据。

而且这样挂载以后,我们无需进入容器,直接在宿主机操作这几个目录里的文件就能同步体现到容器内部,比如修改一些配置,导出数据之类的,不用进入容器直接在宿主机操作即可。

用以上命令运行容器之后,在你的宿主机的 /usr/local/mysql/data 目录就能看到MySQL运行生成的数据库文件了:

33651be8ae70f00d0516783f6d7591f9.png

Docker的数据卷挂载(我习惯称之为挂载目录)功能非常重要,我们运行的任何程序都有需要持久化的数据,如果这些数据直接放在容器内部是非常不安全的。而且 挂载目录还可以实现直接在宿主机操作容器内的数据,也能做到容器间的数据共享,用Docker一定要养成挂载重要数据到宿主机的习惯。

错误排查

上面这个命令是直接后台运行容器的,如果需要调试可以把 -d 参数修改为 -it 参数以在前台运行,在某些情况下你很可能会遇到类似于下面这些错误(可以通过前台运行查看到):

chown: changing ownership of '/var/lib/mysql/': Permission denied

#或者

mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied)

如果出现上述问题,那么你需要关闭 SELINUX ,方法如下:

临时关闭: setenforce 0

永久关闭: vim /etc/selinux/config ,修改 SELINUX 的值为 disabled 然后重启机器即可,看图:

再次运行容器就能看到成功提示了。

常用命令

通过上面的示例基本已经知道了Docker是怎样工作的,下面是一些基本命令,包括最常用的目录挂载功能等命令说明:

docker version|info

#显示Docker信息,常用于查看Docker版本或检测Docker是否正确安装。

docker images

#列出机器上的镜像(images)及信息:REPOSITORY、TAG、IMAGE ID、CREATED、SIZE。

#IMAGE ID列其实是缩写,要显示完整则带上--no-trunc选项。

#-a 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层)

#-no-trunc 显示完整的镜像信息

#-q 静默模式,只显示镜像ID

docker search tomcat

#在docker index中搜索image,搜索的范围是官方镜像和所有个人公共镜像。NAME列的 / 后面是仓库的名字。

docker pull tomcat

#从docker registry server 中下拉image或repository。

#语法:docker pull [OPTIONS] NAME[:TAG|@DIGEST]

#-a 拉取所有 tagged 镜像

#-- disable-content-trust 忽略镜像的校验,默认开启

#上面的命令没有指定参数,在docker v1.2版本及以前,会下载官方镜像的tomcat仓库里的所有镜像

#而从v.13开始只会下载tag为latest的镜像,也可以明确指定具体的镜像

#如:docker pull tomcat:8,后面的8为tomcat版本tag。

docker run -d --name tomcat -p 8081:8080 tomcat:8

#启动容器,语法为:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

#-d 后台运行容器,并返回容器ID,不使用-d我们会看到tomcat启动日志,此时Ctrl+C容器会停止运行。

#-e 指定容器内的环境变量

#-name 指定容器的名称,如果不指定docker会帮我们取一个名字。

#-p 端口映射,宿主机端口:容器端口,上面我们就将宿主机的8081映射到容器的8080端口

#此时我们访问宿主机的ip:8081就能访问容器内的tomcat了。

#-i 以交互模式运行容器,通常与 -t 同时使用。

#-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用

#-v 目录挂载,本地目录:容器目录

docker ps

#查看容器的信息,默认显示当前正在运行中的容器

#-a 查看所有容器

#-l 显示最新启动的一个容器(包括已停止的)

docker start|stop|restart CONTAINER_ID

#启动/停止/重启容器,需要用到容器ID,可以使用docker ps -a 查看所有容器的ID。

docker attach CONTAINER_ID|NAME

#进入容器,后面跟容器ID或者NANE,可以使用docker ps -a 查看所有容器的ID。

#可以认为这是一个过时的命令,更多的docker用户会考虑使用docker exec来实现相同的功能

#但是出于docker官方并没有删除这个命令,我们还是有必要学习一下的。

#进入容器后输入 exit命令可以退出,同时容器停止运行,如若想退出但不停止容器,可以用快捷键Ctrl+P+Q退出。

docker exec -i -t CONTAINER_ID|NAME /bin/bash

#进入容器,推荐使用这种方式。

#语法:docker exec[OPTIONS] CONTAINER COMMAND [ARG...]

#-i 以交互模式运行容器,通常与 -t 同时使用。

#-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用

#示例:docker exec-it mycentos /bin/sh /root/start.sh

#上面这条命令表示在容器 mycentos 中以交互模式执行容器内 /root/start.sh 脚本

docker rm CONTAINER_ID|NAME

#删除一个或多少容器,如:docker rm $(docker ps -a -q),为删除所有停止的容器

#-l 移除容器间的网络连接,而非容器本身

#-v 删除与容器关联的卷

#-f 通过SIGKILL信号强制删除一个运行中的容器

docker rmi CONTAINER_ID|NAME

#删除本地一个或多少镜像

#-f 强制删除;

#--no-prune 不移除该镜像的过程镜像,默认移除;

docker build

#使用 Dockerfile 创建镜像,语法:docker build [OPTIONS] PATH | URL | -

#-f 指定要使用的Dockerfile路径

#-t,--tag 指定镜像的名字及标签:name:tag或者name,可以在一次构建中为一个镜像设置多个标签

Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

初学者一开始可不必关注Dockerfile,待你熟悉Docker的整个体系结构及其运行方式后,再回头看这个就会一目了然了。

FROM

# 指定基础镜像,必须为第一个命令

FROM

FROM:

FROM@

# 示例

FROMdocker.io/centos:latest

MAINTAINER

# 维护者信息

MAINTAINER

# 示例

MAINTAINERguitu "[email protected]"

RUN

# 用于在镜像容器中执行命令,其有以下两种命令执行方式

#shell执行

RUN< command>

#exec执行

RUN[ "executable", "param1", "param2"]

#示例

RUNapk update

RUN[ "executable", "param1", "param2"]

RUN[ "/etc/execfile", "arg1", "arg1"]

# RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。

# 如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

ADD

# 将当前目录下的文件复制到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

ADD...

ADD[ "",... ""]

# 第二中形式用于支持包含空格的路径

# 示例

ADDhom* /mydir/ # 添加所有以"hom"开头的文件

ADDhom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"

ADDtestrelativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/

ADDtest/absoluteDir/ # 添加 "test" 到 /absoluteDir/

# 可以是Dockerfile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件(会自动解压为目录)

# 如果文件或目录不与Dockerfile在同一目录会提示 no such file or directory

COPY

# 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

CMD

# 构建容器后调用,也就是在容器启动时才进行调用。

CMD[ "executable", "param1", "param2"] (执行可执行文件,优先)

CMD[ "param1", "param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)

CMDcommandparam1 param2 (执行shell内部命令)

# 示例

CMDecho"This is a test."| wc -

CMD[ "/usr/bin/wc", "--help"]

# CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT

# 配置容器,使其可执行化。配合CMD可省去"application",只使用参数。

ENTRYPOINT[ "executable", "param1", "param2"] (可执行文件, 优先)

ENTRYPOINTcommandparam1 param2 (shell内部命令)

#示例

FROMubuntu

ENTRYPOINT[ "top", "-b"]

CMD[ "-c"]

# ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。

# Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。

LABEL

# 用于为镜像添加元数据

LABEL=== ...

# 示例

LABELversion= "1.0"deion= "这是一个Web服务器"by= "IT笔录"

# 使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。

# 推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

ENV

# 设置环境变量

ENV

# 之后的所有内容均会被视为其的组成部分,因此,一次只能设置一个变量

ENV= ...

# 可以设置多个变量,每个变量为一个"="的键值对

# 如果中包含空格,可以使用来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行

# 示例

ENVJAVA_HOME /docker/jdk

VOLUME

# 用于指定持久化目录

VOLUME[ "/path/to/dir"]

# 示例

VOLUME[ "/data"]

VOLUME[ "/var/www", "/var/log/apache2", "/etc/apache2"]

# 一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

# 卷可以容器间共享和重用

# 容器并不一定要和其它容器共享卷

# 修改卷后会立即生效

# 对卷的修改不会对镜像产生影响

# 卷会一直存在,直到没有任何容器在使用它

WORKDIR

# 工作目录,类似于cd命令

WORKDIR/path/to/workdir

# 示例

WORKDIR/a (这时工作目录为/a)

WORKDIRb (这时工作目录为/a/b)

WORKDIRc (这时工作目录为/a/b/c)

# 通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。

# 在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

USER

# 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。

# 使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。

# 当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

USERuser

USERuser:group

USERuid

USERuid:gid

USERuser:gid

USERuid:group

# 示例

USERwww

# 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。

# 镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

ARG

# 用于指定传递给构建运行时的变量

ARG=[]

# 示例

ARGsite

ARGbuild_user=www

ONBUILD

# 用于设置镜像触发器

ONBUILD[INSTRUCTION]

# 示例

ONBUILDADD. /app/src

ONBUILDRUN/usr/ local/bin/python-build --dir /app/src

# 当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

构建镜像

了解了上面的命令之后,我们可以尝试着创建我的第一个自制镜像了,以下是我的Dockerfile示例:

#使用的基础镜像

FROMdocker.io/centos:latest

#作者信息

MAINTAINERguitu "[email protected]"

#安装SVN

RUNyum install -y subversion

#添加JAVA环境,下方的文件请换成你Dockerfile目录下的文件,压缩包在构建镜像时会自动解压

ADDjdk-8u231-linux-x64.tar.gz /docker/

ADDapache-tomcat-8.0.53.tar.gz /docker/

#添加环境变量

ENVJAVA_HOME /docker/jdk1.8.0_231

ENVTOMCAT_HOME /docker/apache-tomcat-8.0.53

ENVPATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin

#指定工作目录

WORKDIR/docker/apache-tomcat-8.0.53

#暴露8080端口

EXPOSE8080

#启动时运行tomcat

CMD[ "bin/startup.sh && tail -f logs/catalina.out"]

通过Dockerfile创建镜像:

docker build -t mytomcat8:v0.1 .

通过Dockerfile文件构建镜像完成。

版权申明:本文来源于网友收集或网友提供,如果有侵权,请转告版主或者留言,本公众号立即删除。返回搜狐,查看更多

责任编辑:

;