概念

docker与虚拟机的区别

avatar

虚拟机

基础设施(Infrastructure)。它可以是你的个人电脑,数据中心的服务器,或者是云主机。

主操作系统(Host Operating System)。你的个人电脑之上,运行的可能是MacOS,Windows或者某个Linux发行版。

虚拟机管理系统(Hypervisor)。利用Hypervisor,可以在主操作系统之上运行多个不同的从操作系统。类型1的Hypervisor有支持MacOS的HyperKit,支持Windows的Hyper-V以及支持Linux的KVM。类型2的Hypervisor有VirtualBox和VMWare。

从操作系统(Guest Operating System)。假设你需要运行3个相互隔离的应用,则需要使用Hypervisor启动3个从操作系统,也就是3个虚拟机。这些虚拟机都非常大,也许有700MB,这就意味着它们将占用2.1GB的磁盘空间。更糟糕的是,它们还会消耗很多CPU和内存。

各种依赖。每一个从操作系统都需要安装许多依赖。如果你的的应用需要连接PostgreSQL的话,则需要安装libpq-dev;如果你使用Ruby的话,应该需要安装gems;如果使用其他编程语言,比如Python或者Node.js,都会需要安装对应的依赖库。

应用。安装依赖之后,就可以在各个从操作系统分别运行应用了,这样各个应用就是相互隔离的。

docker

主操作系统(Host Operating System)。所有主流的Linux发行版都可以运行Docker。对于MacOS和Windows,也有一些办法"运行"Docker。

Docker守护进程(Docker Daemon)。Docker守护进程取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理Docker容器。

各种依赖。对于Docker,应用的所有依赖都打包在Docker镜像中,Docker容器是基于Docker镜像创建的。

应用。应用的源代码与它的依赖都打包在Docker镜像中,不同的应用需要不同的Docker镜像。不同的应用运行在不同的Docker容器中,它们是相互隔离的。

区别

虚拟机实现资源的隔离的方式是利用独立的Guest OS,以及利用Hypervisor虚拟化CPU、内存、IO等设备来实现的,Docker不需要Hypervisor实现硬件资源的虚拟化,他利用Namespace 实现了系统环境的隔离,利用了cgroup实现了资源的限制,利用镜像实例实现跟环境的隔离。

Linux namespace技术

namespce是linux的底层概念,在内核层实现,每个docker容器运行在一个docker主进程并且共用一个宿主机内核,各自运行在宿主机的用户空间,彼此之间采用一定的措施互相隔离,以保证自己或宿主机内核不受其他进程的干扰。namespace就是实现隔离的措施。所以运行在Docker容器上的程序,直接使用的都是实际物理机的硬件资源。因此在cpu、内存、利用率上,Docker将会在效率上具有更大的优势。docker启动都是秒级,且兼容性强。

namaspcace一共有6种
avatar

MNT

每个容器都有独立的文件系统挂载点,在创建了一个新的mount namespace后,进程系统对文件系统的挂在/写在动作就不会影响到别的namespace

实验

#拉取两个centos镜像
[root@server1 ~]# docker run -d centos:7 ping baidu.com
5c101d7baa31692d63c4036b0570fa8a2dab1d9a4884e4ee65a410de2e23b631

[root@server1 ~]# docker run -d centos:7 ping baidu.com
3edc6c7e7ed70cfc9dbc9605636aa68c47afaff5cfce2ff8de4a93e5199ca310
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND            CREATED          STATUS          PORTS     NAMES
3edc6c7e7ed7   centos:7   "ping baidu.com"   3 seconds ago    Up 2 seconds              crazy_galileo
5c101d7baa31   centos:7   "ping baidu.com"   19 seconds ago   Up 16 seconds             pedantic_moore

登入两个镜像,各自准备一份一模一样的文件
[root@server1 ~]# docker exec -it 3 bash
[root@3edc6c7e7ed7 /]# pwd
/
[root@3edc6c7e7ed7 /]# whoami
root
[root@3edc6c7e7ed7 /]# cd
[root@3edc6c7e7ed7 ~]# ll
total 4
-rw-------. 1 root root 3416 Nov 13  2020 anaconda-ks.cfg
[root@3edc6c7e7ed7 ~]# echo "this is server1" > 123.txt
[root@3edc6c7e7ed7 ~]# ll
total 8
-rw-r--r--. 1 root root   16 Mar 18 03:09 123.txt
-rw-------. 1 root root 3416 Nov 13  2020 anaconda-ks.cfg
[root@3edc6c7e7ed7 ~]# exit
exit
[root@server1 ~]# docker exec -it 5 bash
[root@5c101d7baa31 /]# cd
[root@5c101d7baa31 ~]# echo "this is server2" > 123.txt
[root@5c101d7baa31 ~]# exit
exit


在宿主机寻找文件,diff存放的是差分文件,merged下存放的是运行时的存储文件,docker使用chroot技术把容器锁定到一个指定的运行目录里
[root@server1 ~]# find / -name "123.txt"
/var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/diff/root/123.txt
/var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/merged/root/123.txt
/var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/diff/root/123.txt
/var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/merged/root/123.txt

[root@server1 ~]# cat /var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/diff/root/123.txt
this is server2
[root@server1 ~]# cat /var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/merged/root/123.txt
this is server2
[root@server1 ~]# cat /var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/diff/root/123.txt
this is server1
[root@server1 ~]# cat /var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/merged/root/123.txt
this is server1

IPC

IPC隔离的是进程间的通信,其会用标识符表示不同的消息队列,进程间通过找到标识符对应的消息队列来完成通信,IPC namespace做的事情就是相同的标识符在不同namespace上对应不同的消息队列,这样不同namespace的进程无法完成进程间通信。

UTS

UTS Namespace用于对主机名和域名进行隔离,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。

PID

PID用于隔离进程号,每个容器内部有一个父进程来管理下属进程,当创建一个PID Namespace时,其第一个进程PID号在容器内部会被映射为1,当这个进程不是前台进程的时候容器会直接停止,用docker ps找不到刚开的容器可能是这个原因。你可以在宿主机用pkill或者kill杀死对应容器的containerd-shim进程,相关容器也能被直接杀死

[root@server1 ~]# yum install psmisc.x86_64 -y

[root@server1 ~]# pstree -p
systemd(1)─┬─NetworkManager(6349)─┬─dhclient(6428)
           │                      ├─{NetworkManager}(6398)
           │                      └─{NetworkManager}(6400)
           ├─agetty(6383)
           ├─auditd(5770)───{auditd}(5771)
           ├─chronyd(6385)
           ├─containerd(6660)─┬─{containerd}(6705)
           │                  ├─{containerd}(6706)
           │                  ├─{containerd}(6707)
           │                  ├─{containerd}(6708)
           │                  ├─{containerd}(6709)
           │                  ├─{containerd}(6751)
           │                  ├─{containerd}(6752)
           │                  └─{containerd}(6754)
           ├─containerd-shim(7552)─┬─ping(7571)
           │                       ├─{containerd-shim}(7554)
           │                       ├─{containerd-shim}(7555)
           │                       ├─{containerd-shim}(7556)
           │                       ├─{containerd-shim}(7557)
           │                       ├─{containerd-shim}(7558)
           │                       ├─{containerd-shim}(7559)
           │                       ├─{containerd-shim}(7560)
           │                       ├─{containerd-shim}(7561)
           │                       ├─{containerd-shim}(7596)
           │                       └─{containerd-shim}(7696)
           ├─containerd-shim(7642)─┬─ping(7663)
           │                       ├─{containerd-shim}(7643)
           │                       ├─{containerd-shim}(7644)
           │                       ├─{containerd-shim}(7645)
           │                       ├─{containerd-shim}(7646)
           │                       ├─{containerd-shim}(7647)
           │                       ├─{containerd-shim}(7648)
           │                       ├─{containerd-shim}(7649)
           │                       ├─{containerd-shim}(7651)
           │                       ├─{containerd-shim}(7683)
           │                       └─{containerd-shim}(7698)
           ├─crond(6366)
           ├─dbus-daemon(6232)───{dbus-daemon}(6348)
           ├─dockerd(6755)─┬─{dockerd}(6831)
           │               ├─{dockerd}(6834)
           │               ├─{dockerd}(6835)
           │               ├─{dockerd}(6836)
           │               ├─{dockerd}(6837)
           │               ├─{dockerd}(6915)
           │               ├─{dockerd}(6916)
           │               ├─{dockerd}(7543)
           │               └─{dockerd}(7590)
           ├─irqbalance(6228)
           ├─lvmetad(3167)
           ├─master(6748)─┬─pickup(7426)
           │              └─qmgr(6750)
           ├─polkitd(6350)─┬─{polkitd}(6393)
           │               ├─{polkitd}(6394)
           │               ├─{polkitd}(6395)
           │               ├─{polkitd}(6396)
           │               ├─{polkitd}(6397)
           │               └─{polkitd}(6402)
           ├─rsyslogd(6649)─┬─{rsyslogd}(7143)
           │                └─{rsyslogd}(7146)
           ├─sshd(6651)─┬─sshd(7474)───bash(7480)───pstree(9856)
           │            └─sshd(7478)───sftp-server(7499)
           ├─systemd-journal(3148)
           ├─systemd-logind(6231)
           ├─systemd-udevd(3185)
           └─tuned(6652)─┬─{tuned}(6917)
                         ├─{tuned}(6918)
                         ├─{tuned}(6919)
                         └─{tuned}(6932)

User

User用于隔离用户资源,一个进程在namespace里的用户和组id与它在host里的id不一样,一个host的普通用户可以在该容器下拥有root权限,但是他的特权被限定在这个容器内

docker0网络

Network

network用于隔离网络资源,每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用networknamespace启动一个vethX接口,这样容器将拥有它自己的桥接IP地址,通常是docker0,而docker0实质就是linux的虚拟网桥

实操

镜像加速

https://cr.console.aliyun.com/cn-hangzhou/instances

avatar

安装部署

安装docker-ce和客户端

yum install wget.x86_64 -y
rm -rf /etc/yum.repos.d/*
wget -O /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y

启动

[root@server1 ~]# systemctl start docker.service
[root@server1 ~]# systemctl enable docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

快速案例(nginx)

[root@server1 ~]# docker pull nginx #拉取镜像
Using default tag: latest
latest: Pulling from library/nginx
f7a1c6dad281: Pull complete
4d3e1d15534c: Pull complete
9ebb164bd1d8: Pull complete
59baa8b00c3c: Pull complete
a41ae70ab6b4: Pull complete
e3908122b958: Pull complete
Digest: sha256:9ddd8cf6d01f497638130950769e279e0b669cd07d11e2bbc4ffead528c9e6e2
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

[root@server1 ~]# docker images #查看现有的镜像
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    c919045c4c2b   2 weeks ago   142MB
(TAG如不在下载时指定默认为lastest)
[root@server1 ~]# docker run -d -p 80:80 nginx
639cb466a53c05eac9eea4786a446be8504834288988bde30b8e1201306c6a65
# -d后台运行容器并且返回容器ID,-p端口映射

[root@server1 ~]# docker ps #查看当前正在运行的镜像
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
#镜像id         使用的镜像    启动容器运行的命令    创建时间        状态            映射                                容器名  
639cb466a53c   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   fervent_clarke

[root@server1 ~]# docker exec -it 639cb466a53c bash #进入这个docker并创建个bash
root@639cb466a53c:/#
root@639cb466a53c:/# exit
exit

[root@server1 ~]# curl 192.168.226.148
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

docker stop 

[root@server1 ~]# docker stop 639cb466a53c # 暂停镜像
639cb466a53c
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

[root@server1 ~]# docker ps -a #显示全部镜像
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
639cb466a53c   nginx     "/docker-entrypoint.…"   17 minutes ago   Exited (0) 29 seconds ago             fervent_clarke
[root@server1 ~]# docker rm 639cb466a53c  #删除
639cb466a53c
[root@server1 ~]# docker ps -a  
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@server1 ~]#

docker信息

[root@server1 ~]# docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.8.0-docker)
  scan: Docker Scan (Docker Inc., v0.17.0)

Server:
 Containers: 1 #当前容器总数
  Running: 0   #运行种
  Paused: 0    #暂停
  Stopped: 1   #停止
 Images: 2      #镜像数
 Server Version: 20.10.13   #服务器版本
 Storage Driver: overlay2   #存储引擎
  Backing Filesystem: xfs   #后端文件系统
  Supports d_type: true     #是否支持d_type
  Native Overlay Diff: true #是否支持差异数据存储
  userxattr: false
 Logging Driver: json-file  #日志文件类型
 Cgroup Driver: cgroupfs    #cgroup类型
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
 Default Runtime: runc      #runtime
 Init Binary: docker-init   #初始化容器的守护进程
 containerd version: 2a1d4dbdb2a1030dc5b01e96fb110a9d9f150ecc
 runc version: v1.0.3-0-gf46b6ba
 init version: de40ad0
 Security Options:          #安全选项
  seccomp
   Profile: default
 Kernel Version: 3.10.0-957.el7.x86_64  #宿主机内核版本
 Operating System: CentOS Linux 7 (Core)    #宿主机操作系统
 OSType: linux                          #宿主机操作系统类型
 Architecture: x86_64                   #宿主机架构
 CPUs: 2                                #宿主机cpu数量
 Total Memory: 972.6MiB                 #宿主机总内存
 Name: server1                          #宿主机名
 ID: SEVK:M4YS:NEBL:SFRQ:72OS:5JDD:HC6Z:NUMM:7MIC:2B3D:KS3Z:4H4G
 Docker Root Dir: /var/lib/docker       #宿主机数据保存目录
 Debug Mode: false
 Registry: https://index.docker.io/v1/  #仓库镜像
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://afh2ckya.mirror.aliyuncs.com/ #镜像加速
 Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

docker目前的默认存储引擎为overlay2,不同存储引擎需要相应的系统支持

https://www.cnblogs.com/youruncloud/p/5736718.html

镜像管理

下载

docker search 镜像名  #搜索镜像
docker pull name:tag  #下载镜像:描述标签,不写默认latest

查看信息


[root@server1 ~]# docker images #列出所有镜像
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

docker inspect:查看镜像详细信息

[root@server1 ~]# docker inspect centos:1
[
    {
        "Id": "sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9",
        "RepoTags": [
            "centos:1",
            "centos:7"
        ],
        "RepoDigests": [
            "centos@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-09-15T18:20:23.99863383Z",
        "Container": "5e4c7bfd35862166e9efd7532208300600114f0acff8f82fd537a57bdd523fe2",
        "ContainerConfig": {
            "Hostname": "5e4c7bfd3586",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/bin/bash\"]"
            ],
            "Image": "sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "DockerVersion": "20.10.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 203936249,
        "VirtualSize": 203936249,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/merged",
                "UpperDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/diff",
                "WorkDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02"
            ]
        },
        "Metadata": {
            "LastTagTime": "2022-03-18T20:43:29.8170514+08:00"
        }
    }
]

docker history:查看各层的创建信息

[root@server1 ~]# docker history centos:1
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
eeb6ee3f44bd   6 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      6 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      6 months ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

删除镜像

[root@server1 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    c919045c4c2b   2 weeks ago    142MB
hello-world   latest    feb5d9fea6a5   5 months ago   13.3kB
centos        7         eeb6ee3f44bd   6 months ago   204MB

[root@server1 ~]# docker rmi feb5d9fea6a5
Untagged: hello-world:latest
Untagged: hello-world@sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

修改镜像标签


[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB
[root@server1 ~]# docker tag centos:7 centos:1
[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       1         eeb6ee3f44bd   6 months ago   204MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

镜像导入导出

可以把本地的镜像导出为一个压缩文件,复制到其他服务器导入使用

导出
docker save 镜像:标签 > /path/name.tar.gz

导入
docker load < /path/name.tar.gz

容器管理

docker create

create创建了一个容器但是不启动他,如果想要启动还需要docker start,语法同run

docker run

选项说明
-d后台运行容器
-i保持标准输入打开
-t分配一个终端,常和i一起用
-p指定端口映射
-P通过NAT随机端口映射
-rm容器退出后就自动删除,不能和-d同时使用
-name别名
-h指定容器内的主机名
-e指定容器内的环境变量
-cpu-shares允许使用cpu的相对权重,默认一个容器能用满一个核
-cpuset-cpus限制容器能使用哪些cpu核心
-m限制容器使用的内存

启动一个容器

[root@server1 ~]# docker run -it centos:1 #创建个终端并使用
[root@2bf2fab97e80 /]# exit
exit

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS                     PORTS     NAMES
2bf2fab97e80   centos:1   "/bin/bash"   31 seconds ago   Exited (0) 5 seconds ago             nice_ellis

[root@server1 ~]# docker run -it -d centos:1#创建个终端并放在后台运行(不进入)
90f1f6e5df2ee13cfc76553f5d4aef6ff8afe240dfc54dea2f4b3d827033440a

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED              STATUS                      PORTS     NAMES
90f1f6e5df2e   centos:1   "/bin/bash"   15 seconds ago       Up 13 seconds                         wizardly_chatelet
2bf2fab97e80   centos:1   "/bin/bash"   About a minute ago   Exited (0) 36 seconds ago             nice_ellis

docker ps 显示

-a :显示所有
-q:只显示容器编号
-n:只显示最近创建的n个容器

端口映射

[root@server1 ~]# docker run -it -d -P nginx #从32768开始随机映射
74880fe87ea549641f40b009a2fa80b989f47492aed4a76b606f52566150608e

[root@server1 ~]# docker run -it -d -p 80:80 nginx #指定映射
b01711c7814987a915b8199de0d77166ac9d2c38643dd23d14a8a1c82440b879

[root@server1 ~]# docker ps -a 
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
b01711c78149   nginx     "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds    0.0.0.0:80->80/tcp, :::80->80/tcp         hardcore_meitner
74880fe87ea5   nginx     "/docker-entrypoint.…"   12 seconds ago   Up 10 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   nervous_swirles

[root@server1 ~]# docker port b01711c78149
80/tcp -> 0.0.0.0:80
80/tcp -> :::80

传递运行命令

容器需要一个前台进程才能保持运行,启动时的指令可以通过在run时后面添加运行指令,也可以在构建镜像的时候指定容器运行时的前台命令

[root@server1 ~]# docker run -it -d centos:1 ping baidu.com
01a5e3f3e8637b9b6b64c6bf014951911cc87d91c871bd41c9c2256236324397
[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND            CREATED         STATUS         PORTS     NAMES
01a5e3f3e863   centos:1   "ping baidu.com"   5 seconds ago   Up 4 seconds             flamboyant_bohr

单次运行

单次运行,运行完就退出

[root@server1 ~]# docker run --rm 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@server1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

停止容器

挂起:docker pause

取消挂起:docker unpause

终止:docker stop

进入容器

atach:退出后容器关闭

exec:单次进入,退出后容器仍在运行

-d :分离模式: 在后台运行

-i :即使没有附加也保持STDIN 打开

-t :分配一个伪终端

[root@server1 ~]# docker exec -it d599ed1cfe2f bash #进入容器分配终端并执行bash
[root@d599ed1cfe2f /]#

nsenter:通过pid进入容器内部,可以方便写成脚本操作

#!/bin/bash 
docker_in()
{ 
    DOCKER_ID=$1 
    PID=`docker inspect -f "{{.State.Pid}}" ${DOCKER_ID}`
    nsenter -t ${PID} -m -u -i -n -p 
}
docker_in $1

删除容器

docker rm ID
如需要删掉正在运行的容器,则需要加-r

全部删除
 docker rm -f `docker ps -aq`

指定容器dns

默认采用宿主机,也可以用--dns来指定

docker run -it --rm --dns 8.8.8.8 centos bash

导入导出容器

可以把正在跑的容器导出,但是导入的时候会变成镜像

导出
docker export -o /path/name.tar 容器

导入
docker import /path/name.tar  镜像:tag

镜像制作

手动镜像制作

docker commit -a "作者" -m "提交时是说明文字" ID 镜像名:标签

dockerfile

dockerfile可以当成一种被docker程序解释的脚本,dockerfile由一条条命令组成,每条命令对应linux下的一条命令,docker讲这些指令翻译成真正的linux命令,并更具指令生成镜像,当之后某个镜像有额外的需求时,只需要在之前的dockerfile添加或修改相应的操作就可以重新生成新的docker镜像。

dockerfile指令每一次执行都会在docker上新建一层,过多无意义的层会导致镜像膨胀过大

dockerfile制作一个镜像的流程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 提交一个新的镜像层
  4. 基于新的镜像层再执行下一个指令
  5. 直到dockerfile中指令执行完毕为止

参数

配置指令:
ARG 定义创建镜像过程中使用的变量,不区分大小写
FROM 指定所创建镜像的基础镜像
LABEL 为生成的镜像添加元数据标签信息
EXPOSE 声明镜像内服务监听的端口,只做声明,没有实际映射功能
ENV 指定环境变量
ENTRYPOINT 指定镜像的默认入口命令,每个file只有一个entrypoint能起效,写多个时最后一个起效,ENTRYPOINT command param1 param2
VOLUME 创建一个数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像时指定自动执行的操作指令
STOPSIGNAL 指定退出的信号值
HEALTHCHECK 配置所启动容器如何进行健康检查
SHELL 指定默认shell类型

操作指令:
RUN 运行指定命令

CMD 
CMD ["executable","param1","param2"] 相当于执行 executable param1 param2 
CMD command param1 param2 在默认的shell中执行,提供给需要交互的应用
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数

启动容器时指定默认执行的命令,cmd跟entrypoint在跟完整命令时功能相似,但是他们并不互斥,可以采用两者相结合的方式来写file,如ent指定默认的运行命令,cmd指定运行参数。如下
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"] 

ADD <src> <dest>添加内容到镜像
COPY <src> <dest>复制内容到镜像

阿里云配置

https://cr.console.aliyun.com/

个人实例--设置密码--命名空间--创建仓库--修改镜像tag--上传镜像

一下命令可以在对应仓库--基本信息里面看到
登录:
docker login --username=阿里云账号全名 registry.cn-hangzhou.aliyuncs.com

从仓库中拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]

将镜像推送到仓库

$ docker login --username= registry.cn-hangzhou.aliyuncs.com
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]

请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数

实例

构建nginx镜像

http://nginx.org/download/

[root@server1 tmp]# mkdir nginx
[root@server1 tmp]# cd nginx/
[root@server1 nginx]# wget http://nginx.org/download/nginx-1.2.1.tar.gz
[root@server1 nginx]# ls
nginx-1.2.1.tar.gz

[root@server1 nginx]# vim Dockerfile
#定义基础镜像
FROM centos:7
#维护者信息
MAINTAINER tokugawa 123.qq.com
#编译安装组件
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
#添加压缩包,一定要处于当前目录下
ADD nginx-1.2.1.tar.gz /usr/local
#配置nginx
RUN cd /usr/local/nginx-1.2.1/ \
&& ./configure --prefix=/usr/local/nginx --with-http_sub_module \
&& make \
&& make install \
&& cd /usr/local/nginx \
&& useradd -s /sbin/nologin nginx \
&& ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx \
&& echo 'test index' > /usr/local/nginx/html/index.html

EXPOSE 80 443
#指定镜像启动进程,让nginx以前台的方式运行
CMD ["nginx", "-g", "daemon off;"]

# 构建镜像,后面有个点不要漏掉!!!!!!!
[root@server1 nginx]# docker build -t nginx:v1 .


如果在构建过程中看docker,会发现有个进程在跑,那个就是新镜像的基地镜像在根据你的设置进行修改
[root@server1 nginx-1.2.1]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
101702c41092   b845f75491a3   "/bin/sh -c 'yum ins…"   32 seconds ago   Up 30 seconds             gracious_feynman


#弄完看见多了一个镜像
[root@server1 nginx]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
centos-nginx   v1        0b4c25729f54   43 seconds ago   553MB
nginx          latest    c919045c4c2b   2 weeks ago      142MB
hello-world    latest    feb5d9fea6a5   5 months ago     13.3kB
centos         1         eeb6ee3f44bd   6 months ago     204MB
centos         7         eeb6ee3f44bd   6 months ago     204MB


#测试
[root@server1 nginx]# docker run -it -d -p 80:80 centos-nginx:v1
30ccc68e51ca1620b972ab44f0fe79cf9de164d0ea5c04289f70bd19133b30f2
[root@server1 nginx]# curl 192.168.226.148
test index


#传上阿里云
[root@server1 nginx]# docker login --username= registry.cn-hangzhou.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@server1 nginx]# docker tag 0b4c25729f54 registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:centos-nginx:v1
Error parsing reference: "registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:centos-nginx:v1" is not a valid repository/tag: invalid reference format
[root@server1 nginx]# docker tag 0b4c25729f54 registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:v1
[root@server1 nginx]# docker push registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:v1

avatar

数据卷

https://mp.weixin.qq.com/s?__biz=MzI1OTY2MzMxOQ==&mid=2247495888&idx=1&sn=39ed455b12cc2e3ad18f5f72c8e6cc21&chksm=ea77c468dd004d7e42aa4a9c095822e41fd3fa01a08156181615fb66f724bc0d03ff228a39bd&mpshare=1&scene=23&srcid=0725FohVQp49EcJQS0khWpUC&sharer_sharetime=1635037154550&sharer_shareid=ac5ffb01d260d9cefd367fe5efc4eb13#rd

联合挂载是一种文件系统,他可以在不修改原始源的情况下创建多个目录,并把内容合并为一个文件的错觉,docker就采用了这种技术。docker的镜像是分层涉及的,且镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据就保存在这一层中。每个容器会分配读写层,不同容器会共享同个镜像的制度曾,我们保存在读写层中的数据会在容器被销毁后丢失,为了防止这种情况,我们可以通过数据卷或者数据卷容器的方式将容器内部的数据挂载都本地宿主机的目录,这样在容器被销毁后数据依然存在。

"Data": {
     "LowerDir": "/var/lib/docker/overlay2/8ceac458023aa93ad2e2fefb6854fed17fa2899710a3593148194286cca6f52c/diff:/var/lib/docker/overlay2/010397015f4f99b4862a0af74065ac93755bff65ccfd7987991e5c544e8255d4/diff:/var/lib/docker/overlay2/01151daf0f2b878a038de5331732e86c0f90da0094197b1fcfd87ae6fc1116c0/diff:/var/lib/docker/overlay2/ee5b6a585a634ebc9f5e18de5d6ee65c2bd370039a766921de149759ed3e0b80/diff:/var/lib/docker/overlay2/1b95802314d82d8b3f9633013e1ef984b28fdbac717c2dc27be59842db4dc06f/diff",

    "MergedDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/merged",

    "UpperDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/diff",

    "WorkDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/work"
            },
LoweDir:image镜像层(只读)
UpperDir:容器上层读写曾
MergeDir:容器文件系统,使用联合文件系统将镜像层和容器曾合并给容器使用
WorkDir:容器在宿主机的工作目录

数据卷挂载

数据卷实际就是宿主机上的目录或者文件,可以直接挂载到容器当中使用

创建目录,创建容器并挂载,验证

[root@server1 ~]# docker run -d -it --name ser1 -v /tmp/web/:/usr/share/nginx/html -p 80:80 nginx
afe02569c5ff5c640004b31ea903b150864492e6acb8a4fc9280b5d7964e8f0a
[root@server1 ~]# docker run -d -it --name ser2 -v /tmp/web/:/usr/share/nginx/html -p 81:80 nginx
eddc33c5b2c76267b50da429b988aec49467d9109dee9f8f9148004b7e6af705
[root@server1 ~]# curl 192.168.226.148
hello nginx!
[root@server1 ~]# curl 192.168.226.148:81
hello nginx!

修改后同步

[root@server1 ~]# docker exec -it ser1 bash
root@afe02569c5ff:/# echo 'hello ser!' > /usr/share/nginx/html/index.html
root@afe02569c5ff:/# exit
exit
[root@server1 ~]# curl 192.168.226.148:81
hello ser!
[root@server1 ~]# curl 192.168.226.148
hello ser!

只读挂载

[root@server1 ~]# docker run -it -d -p 82:80 -v /tmp/web/:/usr/share/nginx/html:ro nginx

[root@server1 ~]# docker exec -it 195364402ff7 bash
root@195364402ff7:/# echo 'hello!' >/usr/share/nginx/html/index.html
bash: /usr/share/nginx/html/index.html: Read-only file system

文件挂载

docker run -d -it --name web2 -v /data/web/index.html:/usr/share/nginx/html/index.html:ro -p 8081:80 nginx

数据卷容器

数据卷容器可以让数据在docker容器之间共享,首先创建一个容器作为server用于卷提供,其他使用这个卷的容器作为客户端

创建卷容器

[root@server1 ~]# docker run -d -it --name web1 -p 8082:80 -v /tmp/web/:/usr/share/nginx/html:ro nginx

启动两个客户端容器

[root@server1 ~]# docker run -d -it --name cli1 -p 8083:80 --volumes-from web1 nginx
78942255bbec92f8fa9473d2b3a56d49a434e534ec152ccb0a5689e595ca6024
[root@server1 ~]# docker run -d -it --name cli2 -p 8084:80 --volumes-from web1 nginx
ddeaff99b9303739d7426ccd3118f3e6cf00acfc5b5a59a26125dac0aef63ffe
[root@server1 ~]# curl 192.168.226.148:8083
hello ser!
[root@server1 ~]# curl 192.168.226.148:8084
hello ser!

卷容器stop后也可以创建新容器,但是卷容器被删除后不可以再创建新容器

docker网络

容器间互联方式

直接联通

用ip进行通信

名称互联

[root@docker-server1 ~]# docker run -d -it --name web1 nginx [root@docker-server1 ~]# docker run -d -it --name web2 --link web1 nginx

web2的hosts文件会对web1进行解析

[root@docker-server1 ~]# docker exec -it web2 bash
root@8a3e9cee9e37:/# cat /etc/hosts 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
ff00::0 ip6-mcastprefix 
ff02::1 ip6-allnodes 
ff02::2 ip6-allrouters 
172.17.0.2 web1 622eff54876f 
172.17.0.3 8a3e9cee9e37

别名互联

使用别名互联后可以防止出现因为容器改名而无法联通

docker run -d -it --name web3 --link web1:nginx-web1 nginx

[root@docker-server1 ~]# docker exec -it web3 bash 
root@c85c73ebf00b:/# cat /etc/hosts 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
ff00::0 ip6-mcastprefix 
ff02::1 ip6-allnodes 
ff02::2 ip6-allrouters 
172.17.0.2 nginx-web1 622eff54876f web1 
172.17.0.4 c85c73ebf00b

网络模式

|网络模式|配置|说明|
|host|–net=host|容器和宿主机共享Network namespace|
|container|–net=container:NAME_or_ID|容器和另外一个容器共享Network namespace。|
|none|–net=none|容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。|
|bridge|–net=bridge|默认|

bridge

dockers的默认网络类型。当dockers进程启动时,会再主机上创建一个docker0的虚拟网桥,此时再启动容器就会链接到这个虚拟网桥上,类似于交换机,这个主机上的所有容器就能通过网桥链接再一个二层网络中
dockers0从子网中分配一个ip给容器使用,并把docker0的ip地址作为容器的默认网关,再主机上创建一对veth pair设备,一段放在新创建的容器的,并命名为eth0作为容器的网卡,另一端放在主机中,以vethxx命名,当这个网络设备加入到docker0中,可以通过brctl show查看
avatar

host

容器将跟宿主机共用一个network namespace,容器将不会虚拟出自己的网卡、IP等,而是使用宿主机的IP和端口。host的优点是网络性能好,但是宿主机上已经使用的端口就不能再用了,另外网络的隔离性也不好

[root@docker-server1 ~]# docker run -d -it --name web7 --network host nginx

container

container的容器和已存在的一个容器共享一个network namespace,除此以外其他的文件系统、进程等还是隔离的,两个容器的进程可以通过lo网卡设备进行通信.注意,当新容器需要的端口已经被老容器占用的时候,可能会导致错误

[root@docker-server1 ~]# docker run -d -it --name web5 --network container:web1 nginx

none

在使用none后,docker容器不会进行仍和网络配置

`[root@docker-server1 ~]# docker run -d -it --name web4 --network none nginx1`

自定义网络

创建一个网络

[root@docker-server1 ~]# docker network create -d bridge --subnet 10.10.0.0/16 --gateway 10.10.0.1 testnet 
74ee6ecdfc0382ac0abb1b46a3c90e3c6a39f0b7388aa9ba99fddc6bac72e8ce 
[root@docker-server1 ~]# docker network list 
NETWORK ID NAME DRIVER SCOPE 
787342a0d883 bridge bridge local 
74ee6ecdfc03 testnet bridge local 
9a6d7244e807 host host local 
beace8354cca none null local

使用自定义网络
[root@docker-server1 ~]# docker run -d -it --name web8 --network testnet nginx

资源限制

容器在默认情况下没有资源限制但对于linux主机来说,如果没有足够的内存来执行重要的系统任务,那就会抛出OOM异常(内存溢出、内存泄漏、内存异常),之后系统会杀进程来释放内存,为了防止这种情况出现,可以对容器的内存使用范围进行限制

https://blog.csdn.net/shenzhen_zsw/article/details/90722333

-m,–memory 内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为 4M

–memory-swap 内存+交换分区大小总限制。格式同上。必须必-m设置的大

–memory-reservation 内存的软性限制。格式同上

–oom-kill-disable 是否阻止 OOM killer 杀死容器,默认没设置

–oom-score-adj 容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0

–memory-swappiness 用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数

–kernel-memory 核心内存限制。格式同上,最小为 4M

容器测压镜像

[root@server1 ~]# docker pull lorel/docker-stress-ng

标签: none

评论已关闭