DOCKER attach命令和DOCKERFILE的小结
docker run = docker create+start 创建并启动
[root@foundation28 ~]# docker history nginx # 可以借此仿写dockerfile
IMAGE CREATED CREATED BY SIZE COMMENT
c82521676580 3 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daem... 0 B
3 weeks ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0 B
3 weeks ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
3 weeks ago /bin/sh -c ln -sf /dev/stdout /var/log/ngi... 0 B
3 weeks ago /bin/sh -c set -x && apt-get update && a... 53.7 MB
3 weeks ago /bin/sh -c #(nop) ENV NJS_VERSION=1.15.2.... 0 B
3 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.... 0 B
4 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX ... 0 B
5 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0 B
5 weeks ago /bin/sh -c #(nop) ADD file:919939fa0224727... 55.3 MB
[root@foundation28 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e993b54ef4b rhel7:v2 "/usr/sbin/sshd -D" 39 hours ago Exited (0) 39 hours ago vm4
a4b9afd4c2a0 rhel7 "bash" 39 hours ago Exited (137) 39 hours ago vm3
04d52b9c8778 rhel7:v1 "/usr/sbin/httpd -..." 39 hours ago Exited (0) 39 hours ago vm2
a43ff01edde9 rhel7 "bash" 40 hours ago Exited (137) 39 hours ago vm1
[root@foundation28 ~]# docker rm -f `docker ps -aq`
7e993b54ef4b
a4b9afd4c2a0
04d52b9c8778
a43ff01edde9
[root@foundation28 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@foundation28 ~]# docker run -d --name vm1 nginx
7ad3f122d922b052f8e948a9e320156b5288abfafbd85f546f05b916ccb89b46
[root@foundation28 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ad3f122d922 nginx "nginx -g 'daemon ..." 4 seconds ago Up 3 seconds 80/tcp vm1
[root@foundation28 ~]# curl 172.17.0.2 直接访问
连接vm1
[root@foundation28 ~]# docker container attach vm1 这样是连接不了,因为nginx默认CMD没有bash,并且结束时会stop这个容器,再次启动需要docker start vm1
[root@foundation28 ~]# docker run -it --name vm2 nginx bash #利用bash连接
root@63951ed504bc:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
此时ctrl+pq打入后台,docker container attach vm2就可以连接了
注意:这种服务类的docker连接上去没有什么意义
[root@foundation28 ~]# docker container exec -it vm1 bash也可以连接
nginx的官方Dockerfile
https://hub.docker.com/_/nginx/
https://github.com/nginxinc/docker-nginx/blob/ddbbbdf9c410d105f82aa1b4dbf05c0021c84fd6/mainline/stretch/Dockerfile
这里面的层次和docker history nginx看到的一致
[root@foundation28 ~]# docker run -d nginx 如果不用--name指定名字,那么就随机
2ba11ad261b4ed7f7e0ff213c38b8c32197fb323b4a39f487f99bae201a41e56
[root@foundation28 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ba11ad261b4 nginx "nginx -g 'daemon ..." 4 seconds ago Up 4 seconds 80/tcp goofy_ride
删除,查看时用CONTAINER ID和NAMES都可以,ID不需要敲全,最少可以区分当前列表下的字符就行
docker
[root@foundation28 ~]# docker inspect 2 直接显示goofy_ride的信息
supervisor:sshd-nginx整合连动
CMD 如果只有一个命令,那如果我们需要运行多个服务的办法是分别在不同的容器中运行,通过 link进行连接,比如先前实验中用到的 ssh,nginx容器。如果一定要在一个容器中运行多个服务可以考虑用 Supervisord 来进行进程管理,方式就是将多个启动命令放入到一个启动脚本中。
1,修改之前的Dockerfile,去掉没必要的层,这样可以减小构建的镜像的大小
2,安装supervisor需要软件和依赖,修改yum源文件,这些都在[docker]下,此文件需要在dockerfile里面写到COPY下,docker的构建下载yum就是dvd.yum,这里用了共享yum源,虽然docker的ip和yum源ip不在同一个网段,但是建立实例时默认做了nat,只要物理机可以连通,docker就可以
[root@foundation28 ~]# cat /etc/yum.repos.d/rhel7.3.repo
[rhel7.3]
name="Remote classroom copy of dvd"
baseurl=http://172.25.254.28/rhel7.3
gpgcheck=0
添加[docker]
[docker]
name=docker
baseurl=http://172.25.254.250/pub/docker
gpgcheck=0
3,建立supervisord.conf 文件,用来整合服务,需要写入Dockerfiel
[root@foundation28 docker]# cat supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:httpd]
command=/usr/sbin/httpd
# 如果有多个服务需要启动可以在文件后继续添加[program:xxx]
4,将sshd和nginx的Dockerfile整合
[root@foundation28 docker]# cat Dockerfile
FROM rhel7
EXPOSE 80 22 # 暴露端口
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd openssh-server openssh-clients supervisor && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:redhat | chpasswd # sshd和httpd需要安装的软件和部分配置,最好先在容器里测试RUN
COPY supervisord.conf /etc/supervisord.conf #docker建立supervisord的配置文件,必须要COPY到docker,存在物理机是无效的
CMD ["/usr/bin/supervisord"]
5,构建镜像
[root@foundation28 docker]# docker build -t rhel7:v1 .
6,建立docker测试
[root@foundation28 docker]# docker run -d --name vm1 -v /tmp/docker/web/:/var/www/html rhel7:v1 #-v 挂载物理机的/tmp/docker/web到vm1的/var/www/html下
0f89f179bb249e4768f2bb282d1ebe5f264cf8e38b41461e23dbb0a99d74481b
[root@foundation28 docker]# cd web/
[root@foundation28 web]# ls
index.html
[root@foundation28 web]# cat index.html
[root@foundation28 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0f89f179bb24 rhel7:v1 "/usr/bin/supervisord" 15 seconds ago Up 14 seconds 22/tcp, 80/tcp vm1
查看ip
[root@foundation28 docker]# docker inspect vm1 | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
[root@foundation28 docker]# curl 172.17.0.2
[root@foundation28 docker]# ssh 172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is 2c:fb:2f:06:4c:23:7a:12:a1:ed:03:db:67:4c:cc:7d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
[email protected]'s password:
-bash-4.2# ls
anaconda-ks.cfg
成功!!!
CMD,RUN,ENTRYPOINT
shell形式不需要[] echo hello
exec形式需要[] [“/bin/echo”,”hello”]
1,CMD命令可以被覆盖
[root@foundation28 ~]# cd /tmp/docker/
[root@foundation28 docker]# ls
Dockerfile dvd.repo ssh supervisord.conf web
[root@foundation28 docker]# mkdir test
[root@foundation28 docker]# cd test/
[root@foundation28 test]# ls
[root@foundation28 test]# vim Dockerfile
[root@foundation28 test]# cat Dockerfile
FROM rhel7
CMD echo "hello world!" # 直接输出hello world
[root@foundation28 test]# docker build -t rhel7:v4 .
[root@foundation28 test]# docker run --rm rhel7:v4
hello world!
[root@foundation28 test]# docker run --rm rhel7:v4 westos # westos不是命令
container_linux.go:247: starting container process caused "exec: \"westos\": executable file not found in $PATH"
docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"westos\": executable file not found in $PATH".
[root@foundation28 test]# docker run --rm rhel7:v4 echo westos #hello world被覆盖
--rm Automatically remove the container when it exits
westos
[root@foundation28 test]# docker history rhel7:v4
IMAGE CREATED CREATED BY SIZE COMMENT
699a3d6bb89e 2 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
0a3eb3fde7fd 4 years ago 140 MB Imported from -
这里的覆盖是指不执行dockerfile里面的CMD,而是执行接在后面的echo westos,连接nginx内部时我们使用bash就是这个原理
2,ENTRYPOINT不会被覆盖
[root@foundation28 test]# docker rmi rhel7:v4
[root@foundation28 test]# vim Dockerfile
[root@foundation28 test]# cat Dockerfile
FROM rhel7
ENTRYPOINT echo "hello world!" # 修改为ENTRYPOINT
[root@foundation28 test]# docker build -t rhel7:v4 .
[root@foundation28 test]# docker run --rm rhel7:v4
--rm Automatically remove the container when
hello world!
[root@foundation28 test]# docker run --rm rhel7:v4 westos
hello world!
[root@foundation28 test]# docker run --rm rhel7:v4 echo westos # 这里不会执行echo westos,没有覆盖
hello world!
3,ENTRYPOINT不会被覆盖,CMD会被覆盖
[root@foundation28 test]# docker rmi rhel7:v4
[root@foundation28 test]# vim Dockerfile
[root@foundation28 test]# cat Dockerfile
FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@foundation28 test]# docker build -t rhel7:v4 .
[root@foundation28 test]# docker run --rm rhel7:v4
hello world
[root@foundation28 test]# docker run --rm rhel7:v4 westos #world被westos覆盖
hello westos
4,ENV变量 shell形式
[root@foundation28 test]# docker rmi rhel7:v4
[root@foundation28 test]# vim Dockerfile
[root@foundation28 test]# cat Dockerfile
FROM rhel7
ENV name westos
ENTRYPOINT echo "hello $name"
[root@foundation28 test]# docker build -t rhel7:v4 .
[root@foundation28 test]# docker run --rm rhel7:v4 # 打印变量
hello westos
5,ENV变量 exec形式
[root@foundation28 test]# docker rmi rhel7:v4
[root@foundation28 test]# vim Dockerfile
[root@foundation28 test]# cat Dockerfile
FROM rhel7
ENV name westos
ENTRYPOINT ["/bin/sh","-c","echo $name"] #-c 命令从-c后的字符串读取。
[root@foundation28 test]# docker build -t rhel7:v4 .
[root@foundation28 test]# docker run --rm rhel7:v4 # 打印变量
westos
注意:RUN 一般用来装软件包,CMD只能写一次,ENTRYPOINT一般执行不可缺少的命令
Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用
cgroup 实现资源限制
Dockerfile生成的镜像是只读的,分层是为了共享资源,图中的顶上两层,就是Docker为Docker容器新建的内容,而这两层恰恰不属于镜像范畴。这两层分别为Docker容器的初始层(Init Layer)与可读写层(Read-Write Layer),初始层中大多是初始化容器环境时,与容器相关的环境信息,如容器主机名,主机host信息以及域名服务文件等。再来看可读写层,这一层的作用非常大,Docker的镜像层以及顶上的两层加起来,Docker容器内的进程只对可读写层拥有写权限,其他层对进程而言都是只读的(Read-Only)。
Dockerfile中的每一条命令,都在Docker镜像中以一个独立镜像层的形式存在。
按照docker官网上的说法,docker的文件系统分为两层:bootfs和rootfs,bootfs包含了bootloader和linux内核。用户是不能对这层作任何修改的。在内核启动之后,bootfs实际上会unmount掉。
DOCKER参数资源限制
过滤死掉的容器ctrl+d结束的
[root@foundation28 test]# docker ps -f status=
created dead exited paused removing restarting running
[root@foundation28 test]# docker ps -f status=exited
docker rm `docker ps -aqf status=exited` 删除死掉的容器
一,权限
1,默认情况下root很多命令没有权力
[root@foundation28 test]# docker run -it --name vm1 ubuntu
root@87d79e57b045:/# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
48: eth0@if49:
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
root@87d79e57b045:/# ip link set down eth0
RTNETLINK answers: Operation not permitted
2,--privileged=true赋予root所有权力
[root@foundation28 ~]# docker run -it --name vm2 --privileged=true ubuntu
root@027abbbfdc83:/# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
50: eth0@if51:
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
root@027abbbfdc83:/# ip link set down eth0
root@027abbbfdc83:/# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
50: eth0@if51:
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
root@027abbbfdc83:/# ip link set up eth0
root@027abbbfdc83:/# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
50: eth0@if51:
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
二,内存
需要stress镜像做压力测试
https://hub.docker.com/r/progrium/stress/
1,限制swap+memory的大小
[root@foundation28 docker]# docker run --rm -it --name vm1 -m 100M --memory-swap 100M stress --vm 1 --vm-bytes 90M
正常运行
-m, --memory string Memory limit
内存大小限制
--memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap
内存和交换空间的总大小限制
--vm n 产生n个进程,每个进程不断调用内存分配malloc和内存释放free函数
--vm-bytes B malloc B bytes per vm worker (default is 256MB)
malloc的全称是memory allocation,中文叫动态内存分配,为每个worker动态内存分配
[root@foundation28 ~]# top # 用top动态查看
2,限制swap+memory的大小,超过限定值压测
[root@foundation28 docker]# docker run --rm -it --name vm1 -m 100M --memory-swap 100M stress --vm 1 --vm-bytes 110M
运行失败
3,不限制swap,逐渐增大内存压力,查看swap最大空间
[root@foundation28 docker]# docker run --rm -it --name vm1 -m 100M stress --vm 1 --vm-bytes 150M
[root@foundation28 docker]# docker run --rm -it --name vm1 -m 100M stress --vm 1 --vm-bytes 190M
运行成功
[root@foundation28 docker]# docker run --rm -it --name vm1 -m 100M stress --vm 1 --vm-bytes 200M
运行失败
swap是memory的1.5-2倍,如果开始使用了swap,那么系统一定会开始慢起来,因为swap是磁盘,慢设备,Swap分区在系统的物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。
[root@foundation28 ~]# free -h -m # m表示单位是M 1G=1024M
total used free shared buff/cache available
Mem: 7.7G 1.3G 253M 385M 6.1G 5.6G
Swap: 7.7G 25M 7.7G
三,CPU
[root@foundation28 ~]# docker run --rm -it --cpu-share 512 stress -c 1
-c, spawn N workers spinning on sqrt()
-c 产生n个进程 每个进程都反复不停的计算随机数的平方根
--cpu-share CPU shares (relative weight)
--cpu-shares 可以设置 CPU 利用率权重,默认为 1024,如果设置选项为 0,则系统会忽略该选项并且使用默认值 1024。通过以上设置,只会在 CPU 密集(繁忙)型运行进程时体现出来。当一个 container 空闲时,其它容器都是可以占用 CPU 的。cpu-shares 值为一个相对值,实际 CPU 利用率则取决于系统上运行容器的数量。
[root@foundation28 ~]# docker run --rm -it --cpu-shares 1024 stress -c 1
[root@foundation28 ~]# docker run --rm -it --cpu-share 512 stress -c 4
[root@foundation28 ~]# docker run --rm -it --cpu-shares 1024 stress -c 4
用top命令对比查看变化
四,限制写的速度
[root@foundation28 ~]# docker run --rm -it --device-write-bps /dev/sda:10M ubuntu
--device-write-bps throttled-device Limit write rate (bytes per second) to a device (default [])
测试:
root@963f48c80d5f:/# dd if=/dev/zero of=file bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 9.95438 s, 10.5 MB/s #速度控制在10M左右
注意:docker处于paused状态时,它的资源如ip,桥接状态等不会被释放,stop之后就释放了
dd命令参数oflag和iflag, 控制源文件和目标文件的读写方式为direct IO,即读或写文件时越过操作系统的读写缓存。如果指定oflag=direct,nonblock,写文件时忽略cache的影响;而如果指定iflag=direct,nonblock,读文件时忽略cache的影响
五,限制读的速度
[root@28 ~]# ll /dev/sda
brw-rw---- 1 root disk 8, 0 Aug 21 19:55 /dev/sda
docker和物理机共享设备资源
[root@28 ~]# docker run --rm -it --device-read-bps /dev/sda:1M --privileged=true ubuntu # --privileged=true 赋予所有权限,默认情况root用户权限也受限制
测试
root@64b8762fa60d:/# dd if=/dev/sda of=file bs=1M count=10 oflag=direct
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 9.9057 s, 1.1 MB/s
时间大概在10s左右,测试成功!!!
Cgroups资源限制
Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制。最初由google的工程师提出,后来被整合进Linux内核。Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC,Docker 使用 cgroups进行资源管理与限制,包括设备、内存、CPU、输入输出
LXC又名Linux container,是一种虚拟化的解决方案,这种是内核级的虚拟化,“lxc”是指linux内核(尤指命名空间以及Cgroup)的一个特性,它允许其他一些沙盒进程运行在一块相对独立的空间,并且能够方便的控制他们的资源调度。
runC是Docker按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。runC是从Docker的libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runc的实现。runc直接与容器所依赖的cgroup/linux kernel等进行交互,负责为容器配置cgroup/namespace等启动容器所需的环境,创建启动容器的相关进程。
/dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里。
/dev /shm/需要注意的一个是容量问题,在linux下,它默认最大为内存的一半大小,使用df -h命令可以看到。但它并不会真正的占用这块内存,如果/dev/shm/下没有任何文件,它占用的内存实际上就是0字节,默认的Linux发行版中的内核配置都会开启tmpfs,映射到了/dev/下的shm目录。既然是基于内存的文件系统,系统重启后/dev/shm下的文件就不存在了,可以通过ls /dev/shm查看下面是否有文件, 如果没有就说明当前系统并没有使用该设备.
安装启动cgroups
[root@server1 ~]# yum search cgroup
[root@server1 ~]# yum install -y libcgroup.x86_64
[root@server1 ~]# cd /cgroup/ # 安装成功才会有这个目录
[root@server1 cgroup]# ls # 如果不启动服务,目录下为空
[root@server1 cgroup]# /etc/init.d/cgconfig start
Starting cgconfig service: [ OK ]
[root@server1 cgroup]# ls
blkio cpu cpuacct cpuset devices freezer memory net_cls
一,限制内存
1,修改/etc/cgconfig.conf
[root@server1 cgroup]# cd memory/
[root@server1 memory]# ls
cgroup.event_control memory.memsw.limit_in_bytes memory.swappiness
cgroup.procs memory.memsw.max_usage_in_bytes memory.usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes memory.use_hierarchy
memory.force_empty memory.move_charge_at_immigrate notify_on_release
memory.limit_in_bytes memory.oom_control release_agent
memory.max_usage_in_bytes memory.soft_limit_in_bytes tasks
memory.memsw.failcnt memory.stat
[root@server1 memory]# cat memory.limit_in_bytes
9223372036854775807 # 这里的意思是没有限制,我有多少内存,就给你多少
[root@server1 memory]# vim /etc/cgconfig.conf
group x1 {
memory {
memory.limit_in_bytes= 209715200; #200M,单位是b
}
}
2,重启服务,注意,不能占用当前目录,/etc/cgconfig.conf中说明了这些目录都是挂载点
[root@server1 memory]# cd
[root@server1 ~]# /etc/init.d/cgconfig restart
3,会在/cgroup/memory/生成一个x1目录
[root@server1 ~]# cd /cgroup/memory/
[root@server1 memory]# ls
cgroup.event_control memory.memsw.limit_in_bytes memory.swappiness
cgroup.procs memory.memsw.max_usage_in_bytes memory.usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes memory.use_hierarchy
memory.force_empty memory.move_charge_at_immigrate notify_on_release
memory.limit_in_bytes memory.oom_control release_agent
memory.max_usage_in_bytes memory.soft_limit_in_bytes tasks
memory.memsw.failcnt memory.stat x1
[root@server1 memory]# cd x1
[root@server1 x1]# ls
cgroup.event_control memory.memsw.limit_in_bytes memory.swappiness
cgroup.procs memory.memsw.max_usage_in_bytes memory.usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes memory.use_hierarchy
memory.force_empty memory.move_charge_at_immigrate notify_on_release
memory.limit_in_bytes memory.oom_control tasks
memory.max_usage_in_bytes memory.soft_limit_in_bytes
memory.memsw.failcnt memory.stat
[root@server1 x1]# cat memory.limit_in_bytes
209715200
4,测试
[root@server1 shm]# free -m
total used free shared buffers cached
Mem: 996 416 579 0 13 271
-/+ buffers/cache: 131 865
Swap: 991 168 823
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=file1 bs=1M count=300 # 必须要用cgexec,否则内存限制不生效
[root@server1 shm]# free -m
total used free shared buffers cached
Mem: 996 216 779 0 13 140
-/+ buffers/cache: 63 933
Swap: 991 0 991
我们划分的内存是300M,但是只减少了200M,内存限制生效,还有100M实际上是swap分区给的
二,限制内存和swap
1,修改/etc/cgconfig.conf
group x1 {
memory {
memory.limit_in_bytes= 209715200;
memory.memsw.limit_in_bytes= 209715200;
}
}
2,重启服务,注意,不能占用当前目录
[root@server1 ~]# /etc/init.d/cgconfig restart
3,测试
[root@server1 ~]# free -m
total used free shared buffers cached
Mem: 996 216 779 0 13 140
-/+ buffers/cache: 63 933
Swap: 991 0 991
[root@server1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=file1 bs=1M count=300300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 2.60735 s, 121 MB/s
[root@server1 ~]# free -m
total used free shared buffers cached
Mem: 996 423 573 0 13 338
-/+ buffers/cache: 70 925
Swap: 991 0 991
这里实际上总共只给了200M
[root@server1 ~]# rm -rf file1
[root@server1 ~]# cd /dev/shm/
[root@server1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=file1 bs=1M count=300
Killed
4,应用:满足以下两个二进制文件的要求
[root@server1 ~]# chmod +x memapp*
[root@server1 ~]# ls
memapp1 memapp2
[root@server1 ~]# ./memapp1
-bash: ./memapp1: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
[root@server1 ~]# yum install -y /lib/ld-linux.so.2[root@server1 ~]# ./memapp1
Process ID is: 1274
Grabbing 4096 pages of memory
Success!
Press any key to exit
[root@server1 ~]# ./memapp2
Process ID is: 1275
Grabbing 8192 pages of memory
Success!
Press any key to exit
解决方案:大于4096小于8192个内存页既可,一个内存页默认是4M
5000*4*1024b
修改配置文件,重启服务
group x1 {
memory {
memory.limit_in_bytes= 20480000;
memory.memsw.limit_in_bytes= 20480000;
}
}
[root@server1 ~]# /etc/init.d/cgconfig restart
创建用户,修改配置文件,启动服务
[root@server1 ~]# useradd redhat
[root@server1 ~]# vim /etc/cgrules.conf
# /etc/cgrules.conf
#The format of this file is described in cgrules.conf(5)
#manual page.
#
# Example:
#
#@student cpu,memory usergroup/student/
#peter cpu test1/
#% memory test2/
# End of file
redhat:memapp1 memory x1/
redhat:memapp2 memory x1/
#rehad:memapp1是对redhat用户的memapp1特定程序做限定,x1是限定策略
[root@server1 ~]# mv memapp* /home/redhat/
[root@server1 ~]# /etc/init.d/cgred start
切换用户,执行文件
[root@server1 ~]# su - redhat
[redhat@server1 ~]$ ls
memapp1 memapp2
[redhat@server1 ~]$ ./memapp1
Process ID is: 1343
Grabbing 4096 pages of memory
Success!
Press any key to exit
[redhat@server1 ~]$ ./memapp2
Process ID is: 1344
Grabbing 8192 pages of memory
Killed
成功!!!
三,限制CPU
1,修改配置文件,重启服务
[root@server1 cpu]# vim /etc/cgconfig.conf
group x2 {
cpu {
cpu.shares=100;
}
}
[root@server1 cpu]# cd
[root@server1 ~]# /etc/init.d/cgconfig restart
Stopping cgconfig service: [ OK ]
Starting cgconfig service: [ OK ]
2,测试
[root@server1 ~]# cgexec -g cpu:x2 dd if=/dev/zero of=/dev/null &
[1] 1357
命令dd if=/dev/zero of=/dev/null永远执行不完,这两个都是无限的,只会消耗cpu资源
top对比这两个命令对cpu的使用量
[root@server1 ~]# dd if=/dev/zero of=/dev/null &
[root@server1 ~]# killall dd
******************************************************************************************************************
[root@server1 ~]# cd /sys/devices/system/cpu/
[root@server1 cpu]# ls # lscpu查看如果有两个cpu,那么这里有cpu0,cpu1
cpu0 cpufreq cpuidle kernel_max offline online possible present
[root@server1 cpu]# cd cpu0/
[root@server1 cpu0]# ls
cache crash_notes node0 topology
# 如果有1个以上cpu,这里会有一个online,echo 0 > online,禁用该cpu,echo 1 > online,启用该cpu
*******************************************************************************************************************
四,限制磁盘
[root@server1 ~]# ll /dev/vda
brw-rw---- 1 root disk 252, 0 Aug 21 21:30 /dev/vda
252,0是磁盘编号
1,修改配置文件,重启服务
group x3 {
blkio {
blkio.throttle.read_bps_device= "252:0 1000000"; # 此磁盘读速1M/s,指定磁盘
}
}
[root@server1 ~]# /etc/init.d/cgconfig restart
2,查看生效的文件
[root@server1 ~]# cd /cgroup/blkio/x3/
[root@server1 x3]# ls
blkio.io_merged blkio.sectors blkio.time
blkio.io_queued blkio.throttle.io_service_bytes blkio.weight
blkio.io_service_bytes blkio.throttle.io_serviced blkio.weight_device
blkio.io_serviced blkio.throttle.read_bps_device cgroup.event_control
blkio.io_service_time blkio.throttle.read_iops_device cgroup.procs
blkio.io_wait_time blkio.throttle.write_bps_device notify_on_release
blkio.reset_stats blkio.throttle.write_iops_device tasks
[root@server1 x3]# cat blkio.throttle.read_bps_device
252:0 1000000
3,测试
[root@server1 ~]# cgexec -g blkio:x3 dd if=/dev/vda of=/dev/null &
# /dev/vda是指定的设备
[root@server1 ~]# iotop # 查看读磁盘的速度
五,更改状态
仓库
Docker 官方已经把仓库封装为镜像,直接通过启动容器就可以部署完成仓库,目录 /var/lib/registry 是仓库存放镜像的位置。除了使用数据卷做镜像存储之外,Registry
还支持将镜像存储到 亚马逊的 S3,OpenStack 的 Swift/Glance 等存储后端。
一,非加密
1,latest是最新版,或者最新稳定版,和版本号2.3.1是一样的
2,导入registry包,docker history registry 可以查看挂载目录在
VOLUME [/var/lib/registry]
[root@foundation28 pub]# mkdir /opt/registry
[root@foundation28 ~]# docker run -d -p 5000:5000 -v /opt/registry/:/var/lib/registry registry:2.3.1
# 端口映射,docker的端口是5000,把本机的/opt/registry/挂载到容器的/var/lib/registry
3,上传nginx
[root@foundation28 ~]# vim /etc/hosts
[root@foundation28 ~]# tail -n 1 /etc/hosts
172.25.254.28 westos.org
[root@foundation28 ~]# docker tag nginx westos.org:5000/nginx # 非加密
[root@foundation28 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest c82521676580 3 weeks ago 109 MB
westos.org:5000/nginx latest c82521676580 3 weeks ago 109 MB
registry latest b2b03e9146e1 6 weeks ago 33.3 MB
[root@foundation28 ~]# docker push westos.org:5000/nginx # 这里必须要走加密,非加密上传失败,westos.org是解析后的域名,也可以写ip
The push refers to a repository [westos.org:5000/nginx]
Get https://westos.org:5000/v1/_ping: http: server gave HTTP response to HTTPS client
[root@foundation28 ~]# docker tag nginx localhost:5000/nginx # 本机不存在加密与非加密
[root@foundation28 ~]# docker push localhost:5000/nginx
The push refers to a repository [localhost:5000/nginx]
08d25fa0442e: Pushed
a8c4aeeaa045: Pushed
cdb3f9544e4c: Pushed
latest: digest: sha256:2de9d5fc6585b3f330ff5f2c323d2a4006a49a476729bbc0910b695771526e3f size: 948
上传成功!!!
[root@foundation28 ~]# cd /opt/registry/
[root@foundation28 registry]# ls
docker
[root@foundation28 registry]# yum install tree -y
[root@foundation28 registry]# tree . # 查看结构,不能拷贝到这里,这里上传的过程是有层次的
3,下载测试
此时下载要先删除之前的localhost:5000/nginx,westos.org:5000/nginx这两个都是对nginx的改名,删除只是去掉名字,否则不会下载
[root@foundation28 registry]# docker rmi westos.org:5000/nginx
Untagged: westos.org:5000/nginx:latest
[root@foundation28 registry]# docker rmi localhost:5000/nginx
Untagged: localhost:5000/nginx:latest
Untagged: localhost:5000/nginx@sha256:2de9d5fc6585b3f330ff5f2c323d2a4006a49a476729bbc0910b695771526e3f
删除nginx,直到没有nginx的镜像
[root@foundation28 registry]# docker rmi nginx
有delete才是删除原始镜像,untagged只是删除一个名字
下载
[root@foundation28 registry]# docker pull localhost:5000/nginx
Using default tag: latest
latest: Pulling from nginx
2da35ff30a7d: Pull complete
831fb1a65ced: Pull complete
7a63da4e8a19: Pull complete
Digest: sha256:2de9d5fc6585b3f330ff5f2c323d2a4006a49a476729bbc0910b695771526e3f
Status: Downloaded newer image for localhost:5000/nginx:latest
4,重命名
[root@foundation28 registry]# docker tag localhost:5000/nginx nginx
5,删除pull的镜像
[root@foundation28 registry]# docker rmi localhost:5000/nginx
*************************************************************************************************************
如何远程走非加密的?这样没有什么意义,因为远程一定是https加密
[root@foundation28 registry]# vim /etc/docker/daemon.json
[root@foundation28 registry]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://u0nb22ie.mirror.aliyuncs.com"],
"insecure-registries": ["westos.org:5000"]
}
[root@foundation28 registry]# systemctl daemon-reload
[root@foundation28 registry]# systemctl restart docker
*******************************************************************************************************************
二,加密
1,解析
[root@28 pub]# tail -n 1 /etc/hosts
172.25.254.28 westos.org
[root@28 tmp]# cd /tmp/docker/
2,获取证书和密钥
这里我们把本机当作容器仓库
[root@28 docker]# mkdir certs
[root@28 docker]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
Generating a 4096 bit RSA private key
..............................................................................................++
...........................++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shannxi
Locality Name (eg, city) [Default City]:xi'an
Organization Name (eg, company) [Default Company Ltd]:westos
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:westos.org
Email Address []:[email protected]
[root@28 docker]# ls
certs
[root@28 docker]# cd certs/
[root@28 certs]# ls
domain.crt domain.key
3,创建容器
[root@28 docker]# docker run -d \
> --restart=always \ # 如果容器关闭了,尝试自动重启
> --name registry \
> -v `pwd`/certs:/certs \ # 挂载点
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ #https加密
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ #证书
> -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ # 密钥
> -p 443:443 \ # 端口映射
> registry:2.3.1 # registry版本
1205aadc80240916d68ac9c4c9396f3fd32af1d1b5028118bf796c8cbb5ba128
4,查看状态
[root@28 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b9255b83fc7a registry:2.3.1 "/bin/registry /et..." 6 seconds ago Up 3 seconds 0.0.0.0:443->443/tcp, 5000/tcp registry
[root@28 docker]# ping westos.org
PING westos.org (172.25.254.28) 56(84) bytes of data.
64 bytes from westos.org (172.25.254.28): icmp_seq=1 ttl=64 time=0.029 ms
5,查看端口转换
[root@28 ~]# iptables -t nat -nL
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 to:172.17.0.2:443
6,复制证书文件
[root@28 docker]# cd /opt/registry/
[root@28 registry]# rm -rf *
[root@28 ~]# cd /etc/docker/
[root@28 docker]# ls
certs.d daemon.json key.json
[root@28 docker]# cd certs.d/
[root@28 certs.d]# mkdir westos.org
[root@28 westos.org]# pwd
/etc/docker/certs.d/westos.org
[root@28 westos.org]# cp /tmp/docker/certs/domain.crt ca.crt
7,上传
[root@28 registry]# docker push westos.org/nginx
The push refers to a repository [westos.org/nginx]
08d25fa0442e: Pushed
a8c4aeeaa045: Pushed
cdb3f9544e4c: Pushed
latest: digest: sha256:2de9d5fc6585b3f330ff5f2c323d2a4006a49a476729bbc0910b695771526e3f size: 948