Docker技术入门基础
Docker有三个非常核心的理念
Comtainer(容器)
images(镜像)
Repositories(仓库)包括远程仓库和本地仓库
1、容器技术概述
NameSpace资源隔离
(IPC通俗来讲是进程之间的通讯)
均为相互独立,不会相互干扰
要想真这个的用好容器技术,保证应用在六个维度的隔离,至少需要使用CentOS7版本或者乌班图,不能使用CentO S6。(内核版本应该在 3.8 以上)
虚拟机技术
全部基于宿主机,启动慢,占用空间大
== 容器技术==
容器相互隔离,但是共享操作系统
1.1、Docker容器引擎介绍
Docker 引擎可以从Docker官网下载,也可以基于GitHub上的源码进行构建。无论是开源版本还是商业版本,都有Linux和Windows版本。
Docker 引擎主要有两个版本:企业版(EE)和社区版(CE)。
每个季度,企业版和社区版都会发布一个稳定版本。社区版会提供4个月的支持,而企业版会提供 12 个月的支持。
从 2017 年第一季度开始,Docker 版本号遵循 YY.MM-xx 格式,类似于 Ubuntu 等项目。例如 2018 年 6 月第一次发布的社区版本为 18.06.0-ce 。
注:2017 年第一季度以前,Docker 版本号遵循大版本号.小版本号的格式,采用的新格式前的最后一个版本就是 Docker 1.13。
Docker是一个非常典型的c/s架构模型
2、Docker的安装部署
2.1、Docker 引擎的安装配置
安装 epel 源
yum install epel-release -y
查看源中有关于docker相关的包
yum list docker --show-duplicates
安装yum-utils
yum install -y yum-utils
将阿里云上 Docker-ce 的 yum 仓库添加到本地操作系统的 yum 仓库中
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
再次查看 yum 仓库中和 Docker-ce 相关的包。
yum list docker-ce --show-duplicates
安装 Docker 引擎
yum install docker -ce
#默认会安装最新版本
将 Docker 引擎设置为开机自启动
systemctl enable docker
将 Docker 引擎启动
systemctl start docker
对 Docker 引擎进行配置
vi /etc/docker/daemon.json
{
"graph": "/data/docker",
"storage-driver": "overlay2",
"insecure-registries": ["registry.access.redhat.com","quay.io"],
"registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
"bip": "172.7.5.1/24",
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true
}
#{工作目录,存储驱动,私有仓库,加速源,docekr 的网络(最好和宿主机有一定的联系),启动时的一些参数,当 Docker 引擎死掉时,依赖 Docker 引擎的容器是否存活}
配置完成之后需要重启 Docker 引擎
systemctl restart docker
2.2、运行第一个容器
docker run hello-world
#自带的容器而非本地的容器
运行过程
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
3、Docker的镜像管理
3.1、Docekr镜像的结构详解
3.2、Docker Hub的注册
在该网址中注册 Docker hub 账号
点击跳转
https://hub.docker.com/
注册过程。。。。
接下来在您的系统中登入Docker账号
#在您的系统中登入远程仓库的账号密码。
docker login docker.io
上图所示为登录成功。
至此,仓库的用户名称注册完成
=登录信息放在哪里了
#登录信息在这里
cat /root/.docker/config.json
base64编码解码可以看到密码
echo "MjIxMTUxMDY3NjpIYW5nMTc3NDk4NTcxNDYuLg==" |base64 -d
3.3、搜索一个镜像
在 Docker Hub 网站上搜索和在命令行中使用该命令是一样的。
docker search alpine
3.4、下载一个镜像
3.4.1、不指定 tag
#下载一个镜像(下拉)不指定 tag
docker pull alpine
系统默认为最新版本(latest)
3.4.2、指定 tag
也可以下载指定的 tag ,不指定的话默认 tag 为 latest。
(案例中没有指定 tag)
#指定 tag,公开仓库,在登陆的情况下可以写全,也可以不写全,但是在私有仓库下,地址必须写全。
docker pull docker.io/library/alpine:3.10.3
3.5、查看本地镜像
#查看本地镜像
docker images
docker image ls
3.6、给镜像打标签
#给你想要的镜像打标签,IMAGE ID是所要打标签镜像的ID
#docker tag IMAGE ID tag
docker tag 965ea09ff2eb docker.io/2211510676/a
lpine:v3.10.3
3.7、推送镜像
# 推送镜像(前提是已经login登录)
docker push docker.io/2211510676/alpine:v3.10.3
推送成功,可以在网址上观察到
3.8、给镜像再打一个标签
#给镜像再打一个标签
docker tag 965ea09ff2eb docker.io/2211510676/alpine:latest
3.9、再次推送镜像
#再次推送镜像
docker push docker.io/2211510676/alpine:latest
3.10、删除镜像
#只是将 tag 删除,并没有实际删除镜像
docker rmi docker.io/2211510676/alpine:latest
执行完成之后,标签没了,但是镜像还在
如何彻底删除镜像呢
#彻底删除镜像
#docker rmi -f IMAGE ID
将本机上的该镜像彻底删除,但是在 Docker Hub 网站上依旧是有的
依旧可以下拉回来
3.11、Docker 镜像特性
下拉时候只会下拉,增量部分,镜像的绝对大小毫无意义,主要看增量大小,尽量控制在几十MB。效果会非常好
4、Docker容器的基本操作
容器是由镜像实例化而来的
4.1、查看本地的容器进程
#列出本地启动的容器的进程
docker ps -a
#(-a 活进程死进程都显示)
4.2、启动容器(运行镜像)
docker run 是日常使用的最频繁的命令之一,同样也是较为复杂的命令之一
命令格式:docker run [ OPTIONS ] IMAGE [ COMMAND ] [ARG…]
OPTIONS:选项
-i:表示启动一个可交互的容器,并持续打开标准输入
-t:表示使用终端关联到容器的标准输入输出上
(-i和-t往往是配合使用的)
-d:表示将容器放置后台运行
–rm:退出后删除容器
–name:表示定义容器唯一名称
IMAGE:表示要运行的镜像
COMMAND:表示启动容器时要运行的命令
4.2.1、交互式启动一个容器
docker run -ti 2211510676/alpine:latest
使用 exit 命令退出之后,状态变为 Exited
4.2.2、非交互式启动容器
#一次性运行的容器使用--rm还是有必要的。
docker run --rm 2211510676/alpine:latest /bin/echo hello
4.2.3、非交互式启动一个后台容器
#如果末尾不加参数,将会直接挂掉
docker run -d --name myalpine 2211510676/alpine:latest /bin/sleep 300
4.3、查看容器
4.3.1、查看运行中的容器
#查看运行中的容器
docker ps -a
4.3.2、查看所有容器
#查看所有的容器
docker ps
4.3.3、查看宿主机进程
虽然容器是和宿主机隔离的,但是依旧可以在宿主机上查询到该进程
有自己的pid
(说明其使用了宿主机的内核)
ps aux|grep sleep|grep -v grep
4.4、进入容器
#docker exec -ti CONTAINER ID /bin/sh
docker exec -ti 8dc6134a9639 /bin/sh
4.5、停止/启动/重启容器
也可以使用容器的名字,将CONTAINER ID 替换为 NAME
4.5.1、停止容器
#停止容器
docker stop CONTAINER ID
4.5.2、启动容器
#启动容器
docker start CONTAINER ID
4.5.3、重启容器
#重启容器
docker restart CONTAINER ID
4.4、删除容器
也可以使用容器的名字,将CONTAINER ID 替换为 NAME
docker rm NAME/CONTAINER ID
当容器正在运行的时候是可以进行删除操作的,需要强制删除(加上参数 -f)
强制删除
#常用脚本
for i in 'docker ps -a|grep -i exit|awk '{print $1}'';do docker rm -f $i;done
#过滤出已经停止的容器,并将其删除。
docker rm 'docker ps -a -q'
4.5、修改/提交容器
4.5.1、修改容器
#只是随意进行了修改,修改完成之后,进行提交
echo hello > 1.txt
退出容器之后,如果容器依旧保持运行,那么我们所做的修改依旧在,当时当容器挂掉之后,容器启动,我们所做的修改就丢失了。我们所做的修改并不在镜像中,而是在容器的可写成,如果想要所做的修改不会消失,需要将其固化到容器里。
4.5.2、提交容器
#将容器提交,会产生新的镜像
docker commit -p NAMES REPOSITORY
4.5.3、验证
启动新镜像查看是否修改依旧存在。
也可以使用export命令。
4.6、导出/导入容器
4.6.1、导出容器
#将容器导为压缩包
docker save IMAGE ID >NAME.tar
#docker save 80de504621d4 > alpine:v3.10.3_with_1.txt.tar
导出容器之后,将镜像删除,然后再重新导入容器
4.6.2、导入容器
#将tar包导入回来
docker load < NAME.tar
#docker load < alpine:v3.10.3_with_1.txt.tar
导入回来之后没有tag,需要我们进行手动操作
docker tag IAMGE ID 2211510676/alpine:v3.10.3_with_1.txt
#docker tag 80de504621d4 2211510676/alpine:v3.10.3_with_1.txt
进行查看
4.7、查看容器的日志
#首先启动hello world容器
docker run hello-world
#查看所启动容器的日志
docker logs (-f) CONTAINER ID
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5c27b9f1949 hello-world "/hello" 12 seconds ago Exited (0) 11 seconds ago tender_wilbur
2570e59b6999 2211510676/alpine:latest "/bin/sleep 300" 40 minutes ago Exited (0) 23 minutes ago myalpine
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker logs -f tender_wilbur
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
5、Docker容器的高级操作
5.1、下载ngnix镜像
#下载1.12.2版本可以指定
docker pull nginx:1.12.2
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker pull nginx:1.12.2
1.12.2: Pulling from library/nginx
f2aa67a397c4: Pull complete
e3eaf3d87fe0: Pull complete
38cb13c1e4c9: Pull complete
Digest: sha256:72daaf46f11cc753c4eab981cbf869919bd1fee3d2170a2adeac12400f494728
Status: Downloaded newer image for nginx:1.12.2
docker.io/library/nginx:1.12.2
#接下来给镜像打上标签
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker tag 4037a5562b03 2211510676/nginx:v1.12.2
5.2、映射端口
docker run -p 容器外端口:容器内端口
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker run --rm --name mynginx -d -p81:80 2211510676/nginx:v1.12.2
4e4c9952aeac1858362a92fd053b37c98445758d8d708208b4c1906453f6a9c8
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e4c9952aeac 2211510676/nginx:v1.12.2 "nginx -g 'daemon of…" 9 seconds ago Up 8 seconds 0.0.0.0:81->80/tcp, :::81->80/tcp mynginx
c5c27b9f1949 hello-world "/hello" 2 days ago Exited (0) 2 days ago tender_wilbur
2570e59b6999 2211510676/alpine:latest "/bin/sleep 300" 2 days ago Exited (0) 2 days ago myalpine
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# netstat -luntp|grep 81
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 5714/docker-proxy
tcp6 0 0 :::81 :::* LISTEN 5719/docker-proxy
#可以发现宿主机81端口已经被监听
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# curl 127.0.0.1:81
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]#
#此时可以通过81端口访问到nginx服务器
5.3、挂载数据卷
docker run -v 容器外目录:容器内目录(目让容器里的某一个目录和宿主机的目录关联起来)
#首先新建一个目录
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# mkdir html
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# cd html
[root@iZ8vbd05x4aqvt8iam0h3mZ html]# wget www.baidu.com -O index.html
--2021-08-18 00:06:27-- http://www.baidu.com/
Resolving www.baidu.com (www.baidu.com)... 110.242.68.3, 110.242.68.4
Connecting to www.baidu.com (www.baidu.com)|110.242.68.3|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2381 (2.3K) [text/html]
Saving to: ‘index.html’
100%[=========================================================================>] 2,381 --.-K/s in 0s
2021-08-18 00:06:27 (316 MB/s) - ‘index.html’ saved [2381/2381]
#以上操作是将百度的首页下载下来。
#开始挂载
[root@iZ8vbd05x4aqvt8iam0h3mZ html]# docker run -d --rm --name nginx_with_baidu -d -p82:80 -v/root/html:/usr/share/nginx/html 2211510676/nginx:v1.12.2
fda92908aabad36c5da795f39f18343e39a0dd6e990e02b9dfacde6b41efa95d
和宿主机指定目录关联之后,即使docker容器的指定目录中不存在宿主机目录中文件,也一样可以访问到
#可以使用inspect命令查询到映射
#docker inspect CONTAINER ID 查看docker容器的详细信息
#docker inspect fda92908aaba|grep share
[root@iZ8vbd05x4aqvt8iam0h3mZ html]# docker inspect fda92908aaba|grep share
"/root/html:/usr/share/nginx/html"
"Destination": "/usr/share/nginx/html",
[root@iZ8vbd05x4aqvt8iam0h3mZ html]#
5.4、传递环境变量
== 非常重要的操作==
#docker run -e 环境变量key=环境变量value 命令
docker run --rm -e E_OPTS=abcdefg 2211510676/alpine:latest printenv
#也可以传递多个环境变量
#传递环境变量可以避免容器成为信息孤岛,而虚拟机相比较来说则是信息孤岛。
5.5、容器内安装软件
yum/apt-get/apt等
docker exec -ti nginx_with_baidu /bin/bash
apt-get update && apt-get install curl -y
在容器内部安装curl工具,之后我们需要将其固化,不然将会导致工具消失。
docker commit -p fda92908aaba 2211510676/nginx:curl
docker push 2211510676/nginx:curl
debian系
容器的生命周期
- 检查本地是否存在镜像,如果不存在即从远程仓库检索
- 利用镜像启动容器
- 分配一个文件系统,并在只读的镜像层外挂载一层可读写层
- 从宿主机配置的网络接口中桥接一个虚拟接口到容器
- 从地址池配置一个ip地址容器
- 执行用户指定的命令
- 执行完毕后容器终止
6、Dockerfile
Docker镜像制作的途径
1、dokcer commit
2、Dockerfile
Docker可以从Dockerfile中的指令来自动构建镜像
两种选择里更多的是使用dcokerfile来构建镜像的。
Dockerfile基本规则:
格式
#为注释
指令(大写)内容(小写)
尽管指令是大小写不敏感的,但是我们前列建议指令用大写,内容用小写表示
Docker是按顺序执行Dockerfile里的指令集合的(从上到下依次执行)
每一个Dokcerfile的第一个非注释指令,必须是 “FROM” 指令,用于为镜像文件构建过程中,指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境中
实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build 会在docker主机(本地)上查找指定的镜像文件,当其在本地不存在时,则会从Docker registry(远端)拉取所需镜像文件
4组核心的Dockerfile指令
- USER / WORKDIR指令
- ADD / EXPOSE指令
- RUN / ENV指令
- CMD / ENTERPOINT指令
USER / WORKDIR
#vi /data/dockerfile/Dockerfile
#这是文件中的内容
FROM 2211510676/nginx:v1.12.2
#指定镜像启动时的用户
USER nginx
#切换到指定目录
WORKDIR /usr/share/nginx/html
接下来构建镜像
docker build . -t docker.io/2211510676/nginx:v1.12.21_with_user_workdir
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# docker run --rm -ti --name nginxfile 2211510676/nginx:v1.12.21_with_user_workdir /bin/bash
nginx@4ae3e756bb39:/usr/share$ pwd
/usr/share
nginx@4ae3e756bb39:/usr/share$ whoami
nginx
nginx@4ae3e756bb39:/usr/share$
ADD / EXPOSE
ADD可以将本地的某个资源固化到docker镜像里
[root@iZ8vbd05x4aqvt8iam0h3mZ ~]# cd /data/dockerfile/
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# cp /root/html/index.html .
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# ll
total 8
-rw-r--r-- 1 root root 62 Aug 29 15:43 Dockerfile
-rw-r--r-- 1 root root 2381 Sep 1 00:27 index.html
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# vi Dockerfile
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# vi Dockerfile
#在文件中键入以下命令
FROM 2211510676/nginx:v1.12.2
ADD index.html /usr/share/nginx/html/index.html
EXPOSE 80
#构造镜像
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# docker build . -t 2211510676/nginx:v1.12.2_with_index_expose
[root@iZ8vbd05x4aqvt8iam0h3mZ dockerfile]# docker run --rm -ti --name nginx123 -P 2211510676/nginx:v1.12.2_with_index_expose /bin/bash
root@7aeba6ab3764:/#
root@7aeba6ab3764:/#
root@7aeba6ab3764:/# pwd
/
root@7aeba6ab3764:/# nginx -g "daemon off;"
111.201.149.89 - - [31/Aug/2021:16:45:43 +0000] "GET / HTTP/1.1" 200 2381 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36" "-"
2021/08/31 16:45:44 [error] 8#8: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 111.201.149.89, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "39.103.189.22:49153", referrer: "http://39.103.189.22:49153/"
111.201.149.89 - - [31/Aug/2021:16:45:44 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://39.103.189.22:49153/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36" "-"
如果启动镜像时使用-p指定端口,则expose指令不生效
RUN / ENV
ENV既可以在dockerfile中充当环境变量,也可以在构建的镜像中充当环境变量。
#在dockerfile文件中键入以下信息
FROM centos:7
ENV VER 9.11.4
RUN yum install bing-$VER -y
#保存退出并执行下列命令
docker build . -t 2211510676/bind:v9.11.4_with_env_run
#验证是否成功
docker run -ti --rm 2211510676/bind:v9.11.4_with_env_run /bin/bash
[root@cbafc8b16cb4 /]# rpm -qa bind
bind-9.11.4-26.P2.el7_9.7.x86_64
CMD / ENTERPOINT
7、综合实验
8、Docker 的网络模型