Docker - 容器

一:容器简介

1.简介

容器是一种轻量级、可移植、并将应用程序进行的打包的技术,使应用程序可以在几乎任何地方以相同的方式运行

  • Docker将镜像文件运行起来后,产生的对象就是容器
  • 容器相当于是镜像运行起来的一个实例
  • 容器具备一定的生命周期
  • 可以借助docker ps命令查看运行的容器,如同在linux上利用ps命令查看运行着的进程那样

2.容器 与 虚拟机

  • 容器和虚拟机一样,都会对物理硬件资源进行共享使用
  • 容器和虚拟机的生命周期比较相似(创建、运行、暂停、关闭等等)
  • 容器中或虚拟机中都可以安装各种应用,如redis、mysql、nginx等。也就是说,在容器中的操作,如同在一个虚拟机(操作系统)中操作一样
  • 同虚拟机一样,容器创建后,会存储在宿主机上:linux上位于/var/lib/docker/containers

容器并不是虚拟机,但它们有很多相似的地方

  • 虚拟机的创建、启动和关闭都是基于一个完整的操作系统。一个虚拟机就是一个完整的操作系统
  • 而容器直接运行在宿主机的内核上,其本质上以一系列进程的结合
  • 容器是轻量级的,虚拟机是重量级的。首先容器不需要额外的资源来管理(不需要Hypervisor、Guest OS),虚拟机额外更多的性能消耗;其次创建、启动或关闭容器,如同创建、启动或者关闭进程那么轻松,而创建、启动、关闭一个操作系统就没那么方便了
  • 也因此,意味着在给定的硬件上能运行更多数量的容器,甚至可以直接把Docker运行在虚拟机上

3.生命周期

虚拟机的生命周期

Docker的生命周期

二:容器生命周期管理

0.查看容器列表

选项 释义
-a 列出当前正在运行的容器+之前运行过的容器
-n=? 显示最近创建的容器
-q 只显示容器的编号
docker ps		# 查看所有正在运行的容器
docker ps -a	# 查看所有正在运行的容器(包括之前运行过的)

1.创建与启动容器

在 Docker 中,真正对外提供服务的还是容器

在Docker容器中,至少有1个应用程序运行在前台

语法

# 创建容器
docker create [选项] [镜像ID]|[镜像名称] [命令]

# 启动容器
docker start [选项] [镜像ID]|[镜像名称] [命令]

# 创建并启动容器
docker run [选项] [镜像ID]|[镜像名称] [命令]

# 这里的 [命令] 是镜像内部默认的命令:Cmd中的,可以用inspect查看
docker run		相当于 docker create + docker start –a		# 前台模式
docker run -d	相当于 docker create + docker start		# 后台模式

选项

选项 释义
-d 以守护进程方式运行
-e 设置容器中的环境变量
-h 指定容器内的主机名
-i 保持标准输出打开
-p 指定映射端口 [宿主主机端口号:容器内部端口号]
-P 随机映射端口
-t 分配一个伪终端
-v 挂载目录(数据卷)到容器
(使用docker commit时,挂载目录无法保存到镜像)
--rm 当容器生命周期结束时,自动删除该容器
--link 链接到另一个容器
--name 为启动的容器设置一个名字(也将名称解析到Docker DNS中)
--network 指定使用哪个网络(bridge、host、none、container)

实例

docker run -d --name nginx -p 80:80 nginx


# 会运行在前台(不推荐)
docker run nginx:1.19.5

# 以守护进程的方式启动
docker run -d nginx:1.19.5

# 指定启动的名称(也将名称加入到Docker DNS中)
docker run -d --name nginx_bak nginx:1.19.5


# 容器生命周期结束后自动删除
docker run -d --rm nginx:1.19.5

# 查看
iptables -vnL

# 启动 并 进入容器
docker run -it centos /bin/bash

# 挂载
docker run -d --rm -v /root/django:/data /python:3.6.8

# 设置环境变量
docker run --name mysql_server -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.32

特点

1.检查本地是否有所需镜像(如果没有,就立即去相应的镜像仓库下载)
2.根据参数启动

2.暂停 与 取消暂停容器

容器可以被暂停,也可以恢复运行

# 暂停1个容器
docker pause [容器ID|容器名称]


# 恢复运行1个容器
docker unpause [容器ID|容器名称]

3.停止容器

docker 终止容器是首先向容器发送 SIGTERM 信号,等待一段时间超时后(默认 10 秒)

再发送 SIGKILL 信号 来终止容器

实例

# 关闭所有容器
docker stop $(docker ps -qa)	# 停止所有的容器


# 先启动nginx
[root@localhost ~]# docker run -d --name nginx -p 80:80 nginx
87d4a352b7543be1aa5abaeafafbd2c7dbda236505b3159d975de1f158e04e23


# 查看已启动的容器
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES
87d4a352b754        nginx               "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   nginx


# 关闭该容器
[root@localhost ~]# docker stop nginx
nginx


# 再次查看已启动的容器
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES


# 此时,可以直接用start再次启动该容器
[root@localhost ~]# docker start nginx
nginx


# 再一次查看已启动的容器(这里可以看到,启动的时间是第1次启动的时间,并不是再次启动的时间)
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
87d4a352b754        nginx               "/docker-entrypoint.…"   3 minutes ago       Up 16 seconds       0.0.0.0:80->80/tcp   nginx

4.终止容器

强制并立即关闭一个或多个处于暂停状态或者运行状态的容器

选项 释义
-s,--signal string 指定发送给容器的关闭信号 (默认“KILL”信号)
docker kill [选项] [容器ID|容器名称]

docker stop和docker kill的区别

# 一 前提知识点:
    1 Linux其中两种终止进程的信号是:SIGTERM和SIGKILL
    2 SIGKILL信号:无条件终止进程信号。
    进程接收到该信号会立即终止,不进行清理和暂存工作。
    该信号不能被忽略、处理和阻塞,它向系统管理员提供了可以杀死任何进程的方法。
    3  SIGTERM信号:程序终结信号,可以由kill命令产生。
    与SIGKILL不同的是,SIGTERM信号可以被阻塞和终止,以便程序在退出前可以保存工作或清理临时文件等。

# 二 docker stop 会先发出SIGTERM信号给进程,告诉进程即将会被关闭。在-t指定的等待时间过了之后,将会立即发出SIGKILL信号,直接关闭容器。
# 三 docker kill 直接发出SIGKILL信号关闭容器。但也可以通过-s参数修改发出的信号。

# 四 因此会发现在docker stop的等过过程中,如果终止docker stop的执行,容器最终没有被关闭。而docker kill几乎是立刻发生,无法撤销。

# 五 此外还有些异常原因也会导致容器被关闭,比如docker daemon重启、容器内部进程运行发生错误等等“异常原因”。

5.重启容器

重启一个或多个处于运行状态、暂停状态、关闭状态或者新建状态的容器
该命令相当于stop和start命令的结合

选项 释义
-f 强行删除容器(会使用 SIGKILL信号)
-v 同时删除绑定在容器上的数据卷
docker rm [选项] [容器ID|容器名称]

6.进入容器

在使用容器的过程中,难免需要进入容器进行排查问题

下面介绍一下进入容器的几种方式

1.attach

通过管道连接容器内的PID为1的进程

attach 是最早 docker 官方推出的进入容器的命令了,不过使用该命令有一个问题

当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示

如果有一个窗口阻塞了,那么其他窗口也无法再进行操作,当所有窗口退出时,容器结束

docker attach nginx
缺点:
  • 没有提供可执行命令的地方
  • attach结束时,容器也跟着结束了(终止的是在前台运行的进程)

2.exec

既 attach 之后,exec 是官方推出的有一个新的进入容器的命令

这个命令相当于在容器中执行一个命令

在宿主主机上 通过exec的方式 在容器内执行某个命令(在外部执行内部的命令)

选项 释义
-i 打开标准输出
-t 创建1个伪终端
docker exec -it [容器ID]

# 实例
docker exec 容器名称 bash

# 退出容器
exit

# 每天5点定时清理日志
00 05 * * * docker exec 容器名 > /eoor/django.log

3.nsenter

(这是Linux中的命令)创建1个管道,连接容器

需要配合 docker inspect 来使用(早期没有 exec 命令时,企业当中最长用的方式之一)

Docker 是用 golang 语言开发,所以它也支持 go 语言的摸版语法

nsenter --target $( docker inspect -f {{.State.Pid}}
nginxv1 ) --mount --uts --ipc --net --pid

4.ssh

在生产环境中排除了使用 docker attach 命令进入容器之后,相信大家第一个想到的就是 ssh

在镜像(或容器) 中安装 SSH Server,这样就能保证多人进入容器且相互之间不受干扰了,相信大家在当前的生产环境中(没有 使用 Docker 的情况)也是这样做的

但是使用了 Docker 容器之后不建议使用 ssh 进入到 Docker 容器内

5.总结

进入 docker container 中一般情况下有 4 种方式,最常用的是 exec nsenter 这2种

Nsenter 和 exec 之间的区别?

  • Exec 是 docker 自带的命令,Nsenter 是 Linux 提供的命令
  • Exec 相当于在容器内执行一个命令,而 Nsenter 是仅仅进入容器之中而已

7.退出容器

# 容器停止并退出
exit


# 容器不停止 退出
Ctrl + P + Q

8.删除容器

普通删除

可以使用 docker rm 命令来删除处于终止或退出状态的容器

语法

docker rm 容器名

强制删除

强制删除一个正在运行的容器

docker rm 容器名	# 删除指定的容器(不能删除正在运行的容器)
docker rm -f 容器名	# 强制删除指定的容器
docker rm -f $(docker ps -qa)	# 删除所有的容器
docker ps -qa | xargs dicker rm	# 删除所有的容器(使用管道符)

实例

# 删除所有已停止的容器
docker rm $(docker ps -a -q)


# 删除所有容器(慎用)
docker rm -f $(docker ps -a -q)

三:其他常用命令

查看容器详情信息

用于查看本地一个或多个容器的详细信息

选项 释义
-f 利用特定Go语言的format格式输出结果
-s 显示总大小
# 语法
docker inspect [选项] [容器ID]

# 实例
[root@localhost ~]# docker inspect 7537a7662db9
[
    {
        "Id": "7537a7662db9e42a2a881fc239245e632b885173dfd3eca36fdca91f46e7f657",
        "Created": "2020-12-01T10:23:41.90270839Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
        ....

后台启动容器

# 命令 docker run -d 镜像名
[root@localhost ~]# docker run -d centos
6ab985f8e3b0bf5384389d291e3bdb94175a285204a6b054f541a59eeb2eaff9

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

# 问题:docker ps之后,发现centos容器停止了

常见的坑:

docker 容器使用后台运行,就必须要有1个前台进程

如果docker发现没有前台进程,就会自动停止

查看日志

选项 释义
-tf 显示日志
--tail 要显示的日志条数
# 语法
docker logs -f -t --tail 10 容器ID


# 编写一段shell脚本
[root@localhost ~]# docker run -d centos /bin/sh -c "while true; do echo Darker; sleep 1; done"
e665be69f9129b3e962309f091a5e87af363254e270f4ab223379f70dde7da92

# 查看正在运行的容器
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e665be69f912        centos              "/bin/sh -c 'while t…"   12 seconds ago      Up 11 seconds                           angry_turing


# 查看容器的日志
[root@localhost ~]# docker logs -tf --tail 10 e665be69f912
2020-12-01T08:09:57.431354440Z Darker
2020-12-01T08:09:58.435476619Z Darker
2020-12-01T08:09:59.440251520Z Darker
2020-12-01T08:10:00.442683974Z Darker
2020-12-01T08:10:01.448639433Z Darker
2020-12-01T08:10:02.453106883Z Darker
2020-12-01T08:10:03.457659408Z Darker
2020-12-01T08:10:04.461011131Z Darker
2020-12-01T08:10:05.464084959Z Darker

查看容器中的进程信息

# 语法
docker top 容器ID

# 实例
[root@localhost ~]# docker top 7537a7662db9
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4855                4838                0                   18:23               ?                   00:00:00            nginx: master process nginx -g daemon off;
101                 4905                4855                0                   18:23               ?                   00:00:00            nginx: worker process

容器重命名

# 语法
docker rename [容器ID] 容器的新名称

# 实例
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
7537a7662db9        nginx               "/docker-entrypoint.…"   4 minutes ago       Up 4 minutes        0.0.0.0:80->80/tcp   awesome_ride
[root@localhost ~]# docker rename 7537a7662db9 my_nginx
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
7537a7662db9        nginx               "/docker-entrypoint.…"   4 minutes ago       Up 4 minutes        0.0.0.0:80->80/tcp   my_nginx

从容器内拷贝文件到主机上

# 语法
docker cp [容器ID]:[容器内路径] [宿主主机路径]
docker cp [宿主主机路径] [容器ID]:[容器内路径] 

# 查看当前主机目录
[root@localhost ~]# ls
anaconda-ks.cfg


# 启动 并 进入容器
[root@localhost ~]# docker run -it centos /bin/bash


# 查看容器内的目录(当前是在根目录)
[root@9575f94d0a03 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var


# 在容器内创建1个文件
[root@9575f94d0a03 /]# touch darker.txt


# 退出该容器
[root@9575f94d0a03 /]# exit
exit


# 查看所有容器(为了找到刚才的容器ID)
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
9575f94d0a03        centos              "/bin/bash"              3 minutes ago       Exited (0) 17 seconds ago                       wonderful_driscoll
e015ce3ec587        centos              "/bin/bash"              5 minutes ago       Exited (0) 5 minutes ago                        naughty_chaplygin


# 将刚刚在容器中创建的文件拷贝到主机上
[root@localhost ~]# docker cp 9575f94d0a03:/darker.txt /home

四:总结

练习

1.安装并启动mysql

# 拉取镜像
[root@localhost ~]# docker pull mysql:5.7.32

# 运行,并设置root密码
[root@localhost ~]# docker run --name mysql_server -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.32

# 查看已启动容器
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
9ce38e811c19        mysql:5.7.32        "docker-entrypoint.s…"   9 seconds ago       Up 8 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   mysql_server

# 进入该容器,进行操作(此时,localhost ~ 会变成该容器的id)
[root@localhost ~]# docker exec -it mysql_server bash
root@9ce38e811c19:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.32 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>


# 此时,也可以通过Navicat等工具,远程连接该MySQL
ssh通道连接服务器的,MySQL账号密码用该MySQL容器的

2.安装并启动nginx,并打开指定网页

# 先创建1个目录,用于挂载
mkdir /test

# 在该目录下创建一个index.html
vim /test/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello World</h1>

</body>
</html>

# 运行nginx,端口映射 80:80 将宿主机的/test/挂载到/usr/share/nginx/html中
docker run -d -it --name nginx_service -v /test/:/usr/share/nginx/html -p 80:80 nginx


# 访问
curl 127.0.0.1:80/index.html
posted @ 2020-12-18 21:10  轻描丨淡写  阅读(234)  评论(0编辑  收藏  举报