0


一篇文章教你玩转Docker!

准备工作:

搭建本地网络源:

cd /etc/yum.repos.d/
vim docker-ce.repo

一、基础操作

#拉取镜像
[root@decker-node1 ~]# docker pull nginx:1.26-alpine

#查看本地镜像
[root@decker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
nginx                latest    5ef79149e0ec   12 days ago     188MB
busybox              latest    65ad0d468eb1   15 months ago   4.26MB
timinglee/game2048   latest    19299002fdbe   7 years ago     55.5MB
timinglee/mario      latest    9a35a9e43e8c   8 years ago     198MB

#查看镜像(nginx)
[root@decker-node1 ~]# docker image inspect nginx

#保存镜像
[root@decker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz

[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息
[root@Docker-node1 ~]# docker stop busybox #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox #开启停止的容器
[root@docker-node1 ~]# docker load -i game2048.tar.gz 
[root@docker-node1 ~]# docker load -i mario.tar.gz 
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED       SIZE
timinglee/game2048   latest    19299002fdbe   7 years ago   55.5MB
timinglee/mario      latest    9a35a9e43e8c   8 years ago   198MB

[root@docker-node1 ~]# docker run -d --rm --name game1 -p 80:8080 timinglee/mario

[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE             COMMAND                   CREATED         STATUS         PORTS                                   NAMES
475d1ada9324   timinglee/mario   "python3 -m http.ser…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->8080/tcp, :::80->8080/tcp   game1 

[root@docker-node1 ~]# docker rm -f game1 
game1
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS 

二、构建镜像

1、参数示例及使用方法

**FROM **

指定base镜像** egFROM busybox:version **

**COPY **

复制文件** egCOPY file /file 或者 COPY [“file”,”/”] **

*MAINTAINER 指定作者信息,比如邮箱 eg*MAINTAINER ****user@example.com **

在最新版的docker中用LABEL KEY="VALUE"代替

**ADD **

*功能和copy相似,指定压缩文件或url eg: ADD test.tar /mnt 或者 eg***ADD **

http://ip/test.tar** /mnt **

**ENV **

指定环境变量** egENV FILENAME test **

**EXPOSE **

暴漏容器端口** egEXPOSE 80 **

**VOLUME **

申明数据卷,通常指数据挂载点** egVOLUME [“/var/www/html”] **

**WORKDIR **

切换路径** egWORKDIR /mnt **

**RUN **

在容器中运行的指令** eg: touch file **

**CMD **

在启动容器时自动运行动作可以被覆盖** egCMD echo $FILENAME ****会调用 **

shell**解析 egCMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用shell****解析 **

**ENTRYPOINT **

*CMD*功能和用法类似,但动作不可被覆盖 **

[root@decker-node1 ~]# cd docker/
[root@decker-node1 docker]# touch dockerfile
[root@decker-node1 docker]# vim dockerfile 

volume:
docker inspect test #查看挂载点、宿主机的目录

2、Docker构建实例

删除没有挂在成功的镜像:

[root@decker-node1 docker]# docker rmi `docker images | awk '/none/{print $2}'`
[root@decker-node1 docker]# docker rmi 04f578596280 931faa592f44

加载centos7镜像:

[root@decker-node1 docker]# docker load -i centos-7.tar.gz

编写构建文件:

开始构建:

root@decker-node1 docker]# docker build -t nginx:v1 .

构建时出现报错:yum时候出现问题->原因是centos镜像的问题

dnf install httpd -y
#配置文件的端口改为8888
systemctl restart httpd

新加cdroom:

挂载本地软件仓库sr1:

开启centos7容器:

[root@decker-node1 ~]# docker run -it --name centos centos:7

配置该容器的本地软件仓库:

将配置好的容器提交镜像(centos的repo版本)

[root@decker-node1 ~]# docker commit -m "add repo" centos centos:repo

修改构建文件:

继续构建nginx镜像:

[root@decker-node1 docker]# docker build -t busybox:v1 .

可以看到nginx:vi版本有356MB,可以进行优化减少大小。

3、镜像优化示例

缩减镜像层:

[root@decker-node1 docker]# vim dockerfile 

可以看出nginx:v1版本变小了(292MB):

多阶段构建:

可以看出nginx:v2版本变小(210MB):

使用最精简镜像

加载nginx1.23镜像和最小精简镜像:

[root@decker-node1 docker]# docker load -i nginx-1.23.tar.gz
[root@decker-node1 docker]# docker load -i debian11.tar.gz

编辑构建文件:

可以看到nginx:v3版本只有34.5MB:

三、docker镜像仓库管理

1、docker hub

2、搭建私有仓库

(1)、搭建简单无加密私有仓库

下载镜像:

[root@decker-node1 ~]# docker load -i registry.tag.gz 

开启容器:

[root@decker-node1 ~]# docker run -d -p 5000:5000 --restart=always registry

给要上传的镜像添加标签:

[root@decker-node1 ~]# docker tag nginx:v2 172.25.254.100:5000/nginx:v2

配置非加密端口:

daemon.json是 Docker 的配置文件,通常位于/etc/docker/目录下(不同系统可能有所不同)。
以下是一个示例的daemon.json文件内容及解释:
json
复制
{
"registry-mirrors": ["https://your-custom-mirror.com"],
"insecure-registries": ["your-insecure-registry:port"],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
解释:
"registry-mirrors": 指定 Docker 镜像加速地址,可以提高拉取镜像的速度。
"insecure-registries": 指定不安全的私有镜像仓库地址,如果你的私有仓库没有使用 HTTPS,需要将其添加到这个列表中。
"max-concurrent-downloads": 设置同时下载的最大层数,可根据系统资源和网络情况调整。
"log-driver": 设置日志驱动,这里设置为json-file表示以 JSON 格式的文件记录日志。
"log-opts": 日志相关的选项,这里设置了单个日志文件最大为10m,最多保留3个日志文件。
你可以根据自己的需求对daemon.json进行配置。修改后,通常需要重启 Docker 服务使配置生效。

[root@decker-node1 ~]# vim /etc/docker/daemon.json
[root@decker-node1 ~]# systemctl restart docker

上传:

[root@decker-node1 ~]# docker push 172.25.254.100:5000/nginx:v2

查看镜像上传:

[root@decker-node1 docker]# curl 172.25.254.100:5000/v2/_catalog

(2)、搭建加密的私有仓库

生成认证证书和key

#删除配置文件的非加密配置
[root@decker-node1 ~]# vim /etc/docker/daemon.json 
[root@decker-node1 ~]# systemctl restart docker
mk[root@decker-node1 ~]# mkdir certs

#添加解析
[root@decker-node1 ~]# vim /etc/hosts
172.25.254.100  decker-node1 reg.gaoyingjie.org
#生成key和证书
[root@decker-node1 ~]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout certs/gaoyingjie.org.key \
> -addext "subjectAltName = DNS:reg.gaoyingjie.org" \
> -x509 -days 365 -out certs/gaoyingjie.org.crt

让docker读取证书:

[root@decker-node1 ~]# mkdir /etc/docker/certs.d/reg.gaoyingjie.org/ -p
[root@decker-node1 ~]# cp /root/certs/gaoyingjie.org.crt /etc/docker/certs.d/reg.gaoyingjie.org/ca.crt
[root@decker-node1 ~]# systemctl restart docker

开启registry容器:

[root@decker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/gaoyingjie.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/gaoyingjie.org.key registry:latest

#-v: 挂载目录,容器下有该目录

添加tag标签:

[root@decker-node1 docker]# docker tag busybox:latest reg.gaoyingjie.org/busybox:latest

上传:

[root@decker-node1 docker]# docker push reg.gaoyingjie.org/busybox:latest

查看上传的镜像:

[root@decker-node1 docker]# curl -k https://reg.gaoyingjie.org/v2/_catalog

(3)、搭建用户认证的私有仓库

解释:需要用户输入密码才能的上传到搭建的私有仓库。

创建认证文件(使用md5加密):

[root@decker-node1 ~]# mkdir auth
[root@decker-node1 ~]# htpasswd -Bc auth/htpasswd gaoyingjie    #-B:最强加密方式
New password: 
Re-type new password: 
Adding password for user gaoyingjie

开启容器,
添加认证到registry容器中:

[root@decker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/gaoyingjie.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/gaoyingjie.org.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd"  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry

登录私有仓库:

[root@decker-node1 ~]# docker login reg.gaoyingjie.org
Authenticating with existing credentials...
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/#credential-stores

Login Succeeded

上传镜像:

[root@decker-node1 ~]# docker push reg.gaoyingjie.org/busybox:latest 

查看上传的镜像:

curl -k https://172.25.254.100/v2/ catalog -ugaoyingjie:gaoyingjie

若未登录私有仓库:则显示上传失败。

3、构建企业级私有仓库-harbor

在第2步的基础上部署harbor

[root@docker ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker ~]# ls
anaconda-ks.cfg certs harbor-offline-installer-v2.5.4.tgz
auth harbor
[root@docker ~]# cd harbor/
[root@docker harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker harbor]# vim harbor.yml

生成证书和key:

[root@docker-harbor harbor]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/gaoyingjie.org.key -addext "subjectAltName = DNS:reg.gaoyingjie.org" -x509 -days 365 -out certs/gaoyingjie.org.crt

将证书和key放入配置文件里指定目录:

[root@decker-node1 harbor]# mkdir /data
[root@decker-node1 harbor]# cp -r /root/certs/ /data/
[root@decker-node1 harbor]# ls /data/
certs

#让docker读取证书
[root@docker-harbor certs]# cp /root/certs/gaoyingjie.org.crt /etc/docker/certs.d/reg.gaoyingjie.org/ca.crt

安装harbor:

[root@decker-node1 harbor]# ./install.sh  --with-chartmuseum 

启动harbor:

[root@decker-node1 harbor]# docker compose stop
[root@decker-node1 harbor]# docker compose up -d

本地解析:

登录harbor:浏览器输入reg.gaoyingjie.org(仓库名,也就是hostname)

新建项目:

上传镜像到仓库新建项目newtest:

#登录harbor私有仓库
#先将之前的退出,如果没登陆过则不用
[root@decker-node1 harbor]# docker logout reg.gaoyingjie.org
Removing login credentials for reg.gaoyingjie.org
#登录
[root@decker-node1 harbor]# docker login reg.gaoyingjie.org
Username: admin
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/#credential-stores

Login Succeeded

添加标签:

[root@decker-node1 harbor]# docker tag nginx:v3 reg.gaoyingjie.org/newtest/nginx:v3

上传镜像:

[root@decker-node1 harbor]# docker push reg.gaoyingjie.org/newtest/nginx:v3

可以看到已上传nginx

小tip:

#一键加载镜像
#所有的镜像文件在/root/images下
[root@docker-harbor images]# for i in `ls /root/images`; do docker load -i $i; done

#一键清除所有容器(慎重)
[root@docker-harbor harbor]# docker container prune -f
#一键添加标签
[root@docker-harbor ~]# docker images | awk 'NR>1{system("docker tag "$1":"$2" reg.gaoyingjie.org/library/"$1":"$2)}'

#一键push
[root@docker-harbor ~]# docker images | awk '/reg.gaoyingjie.org/{system("docker push "$1":"$2)}'

#一键删除某些镜像
[root@k8s-master ~]# docker images | awk '/reg.timinglee.org/{system("docker rmi "$1":"$2)}'

四、docker的网络

修改防火墙策略

[root@decker-node1 ~]# grubby --update-kernel ALL --args iptables=true
[root@decker-node1 ~]# reboot

1、dacker的原生网络

(1)、bridge

(2)、host

(3)、none

2、docker的自定义网络

自定义桥接:原生的桥接模式是没有dns模块,所以要用自定义桥接,可以用容器名称通信。

容器的开启顺序不同会导致ip不同,会导致容器之间通讯出现问题。


[root@docker-node1 ~]# docker network create mynet1 -d bridge 
7e2fe742ddd7221d316d60276be1078e28f09ae1b2b6ca1ec79f8df5ca31ceda
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ad53e07c3e80   bridge    bridge    local
12e886188af6   host      host      local
7e2fe742ddd7   mynet1    bridge    local
cf8dda13f1cb   none      null      local

[root@docker-node1 ~]# docker run -it  --name test1 --network mynet1 busybox
[root@docker-node1 ~]# docker run -it  --name test2 --network mynet1 busybox

#删除网络
[root@docker-node1 ~]# docker network rm mynet1 
mynet1
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ad53e07c3e80   bridge    bridge    local
12e886188af6   host      host      local
cf8dda13f1cb   none      null      local

可以看出,两个容器test1和test2处于同一网络,之间可以用ip通信,也可以用容器名通信。而传统的桥接模式是不能用容器名称通信的。

3、不同的自定义网络之间的通信

有两种情况:用相同网络栈和不同网络栈

(1)、容器用不同的网络栈

#创建两个自定义桥接网络
[root@docker-node1 ~]# docker network create mynet1 -d bridge 
2a79172a5fe1a4b433c3daf4bdefaabf89b0a656aa5e7a07c007ae6a05a7b078
[root@docker-node1 ~]# docker network create mynet2 -d bridge 
a79928a1c7ec8d4037863138b02a5fb967254ee3a560388572b0b16fd6ae0745

可以看到不同自定义网络是是不能通信的。

将一个容器加入网卡接入另一个网络中:

#将test2接入mynet1网络中
#所以test2容器有172.28.0.2(mynet1)和172.19.0.2(mynet2)两个ip 
[root@docker-node1 ~]# docker network connect mynet1 test2

(2)、容器用相同的网络战栈-joined网络

示例1:

[root@docker-node1 ~]# docker run -d --name test1 --network mynet1 nginx
8d1ad6dd316d38816f509a8db9ab1c057d766e8c92b437b98b4c72578eb4700c

#用mynet2的网络栈
[root@docker-node1 ~]# docker run -d --name test2 --network container:test1 centos:7 
7ae5ac441717042123b0ddf964a1918725dfc2070709200772d46a900c79b343

镜像centos是没有web服务的,但是test1和test2用了同个网络栈,所以test2有wab服务:

示例2:

phpmyadmin和mysql两个容器共用一个网络栈,phpmyadmin通过回环接口就能管理mysql,更安全。

[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz 

[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz 

[root@docker-node1 ~]#  docker network create mynet1 -d bridge 

#开启phpmyadmin容器
[root@docker-node1 ~]# docker run -d --name mysqladmin --network mynet1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest

#开启mysql容器
[root@docker-node1 ~]# docker run -d --name mysql \
> -e MYSQL_ROOT_PASSWORD='gyj' \
> --network container:mysqladmin \
> mysql:5.7

登录:浏览器输入172.25.254.100

在mysql容器内执行命令:

[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# 

也可以用phpmyadmin管理数据库。

4、容器内外网的访问

(1)、容器访问外网

(2)、外网访问容器

5、容器的跨主机网络通信

macvlan

在两台docker主机上各添加一块网卡,打开网卡混杂模式:

[root@docker-node1 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ip link set up eth1

两主机添加macvlan网络:

[root@docker-node2 ~]# docker network create -d macvlan --subnet 1.1.1.0/24 --gateway 1.1.1.1 -o parent=eth1 macvlan1

开启容器:

[root@docker-node1 ~]# docker run -it --name test1 --network macvlan1 --ip 1.1.1.100 --rm busybox
[root@docker-node2 ~]# docker run -it --name test2 --network macvlan1 --ip 1.1.1.200 --rm busybox

测试:开处于不同主机的两个容器是否可以通信

五、docker的数据卷管理

1、bind mount数据卷

  • 是将主机上的目录或文件mount到容器里。
  • 使用直观高效,易于理解。
  • 使用 -v 选项指定路径。
[root@docker-node1 ~]# docker run -it --rm -v /test1:/data1:rw -v /etc/passwd:/data2/passwd:ro busybox

2、docker managed数据卷

  • bind mount必须指定host文件系统路径,限制了移植性
  • docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录
  • 默认创建的数据卷目录都在 /var/lib/docker/volumes 中
  • 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中
[root@docker-node1 ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='gyj' mysql:5.7

[root@docker-node1 ~]#cd /var/lib/docker/volumes/09c6f145e4449d1cbdfd5118fdd869adb32573a4195c18dc22a6ac93f3c7596b/_data/
[root@docker-node1 _data]# touch newfile

#进入容器查看是否有newfile
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# cd /var/lib/mysql
bash-4.2# ls

可以看到没有指定数据卷目录,默认在挂载到host的/var/lib/docker/volume/容器id/_data中,在此目录下新建文件,可以在容器内部的/var/lib/容器名/中看到新文件。

3、数据卷容器

数据卷容器(Data Volume Container)是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间 共享数据卷。

#建立数据卷容器
[root@docker ~]# docker run -d --name datavol \
-v /tmp/data1:/data1:rw \
-v /tmp/data2:/data2:ro \
-v /etc/resolv.conf:/etc/hosts busybox

#使用数据卷容器
[root@docker ~]# docker run -it --name test --rm --volumes-from datavol busybox

六、docker的安全优化

[root@docker-node1 ~]# docker run -d --name web nginx
516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7
[root@docker-node1 ~]# docker inspect web | grep Pid
            "Pid": 1898,
            "PidMode": "",
            "PidsLimit": null,
[root@docker-node1 ~]# cd /proc/
[root@docker-node1 proc]# cd 1898
[root@docker-node1 1898]# cd ns
[root@docker-node1 ns]# ls
cgroup  ipc  mnt  net  pid  pid_for_children  time  time_for_children  user  uts

[root@docker-node1 ns]# cd /sys/fs/cgroup/
[root@docker-node1 cgroup]# ls
blkio    cpu,cpuacct  freezer  misc              net_prio    rdma
cpu      cpuset       hugetlb  net_cls           perf_event  systemd
cpuacct  devices      memory   net_cls,net_prio  pids
[root@docker-node1 cgroup]# cd memory/
[root@docker-node1 memory]# cd docker/
[root@docker-node1 docker]# ls
516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7
cgroup.clone_children
cgroup.event_control
***

[root@docker-node1 docker]# cd 516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7/
[root@docker-node1 516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7]# ls
cgroup.clone_children               memory.memsw.failcnt
cgroup.event_control                memory.memsw.limit_in_bytes
cgroup.procs                        memory.memsw.max_usage_in_bytes
memory.failcnt                      memory.memsw.usage_in_bytes
memory.force_empty                  memory.move_charge_at_immigrate
memory.kmem.failcnt                 memory.numa_stat
memory.kmem.limit_in_bytes          memory.oom_control
memory.kmem.max_usage_in_bytes      memory.pressure_level
memory.kmem.slabinfo                memory.soft_limit_in_bytes
memory.kmem.tcp.failcnt             memory.stat
memory.kmem.tcp.limit_in_bytes      memory.swappiness
memory.kmem.tcp.max_usage_in_bytes  memory.usage_in_bytes
memory.kmem.tcp.usage_in_bytes      memory.use_hierarchy
memory.kmem.usage_in_bytes          notify_on_release
memory.limit_in_bytes               tasks
memory.max_usage_in_bytes

1、docker的资源限制

(1)、限制cpu的使用量

[root@docker-node1 ~]# docker run -it --rm --name test1 --cpu-period 100000 --cpu-quota 20000 ubuntu
root@3c63c90f85ef:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@3c63c90f85ef:/# top

[root@docker-node1 ~]# docker run -it --rm --name test2 --cpu-period 100000 --cpu-quota 30000 ubuntu
root@9ba159f17589:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@9ba159f17589:/# top

(2)、限制cpu的优先级

[root@docker-node1 ~]# docker run -it --rm --name test1 --cpu-shares 100  ubuntu
root@0d33e9d6b5a3:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@0d33e9d6b5a3:/# top

[root@docker-node1 ~]# docker run -it --rm --name test2  ubuntu
dd if=/dev/zero of=/dev/null &root@c30ea1c45318:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@c30ea1c45318:/# top

(3)、限制内存使用

上传工具:

libcgroup-0.41-19.el8.x86_64.rpm
libcgroup-tools-0.41-19.el8.x86_64.rpm

[root@docker-node1 ~]# dnf install *.rpm -y

开启容器并限制内存:

[root@docker-node1 ~]# docker run -d --rm --name test1 --memory 200M --memory-swap 200M nginx
9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616
[root@docker-node1 ~]# cd /sys/fs/cgroup/
[root@docker-node1 cgroup]# cgexec -g memory:docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=150

查看该容器id下的内存资源限制文件,可以看到200m的字节为 209715200,也可通过echo写入文件将内存限制从200mb改为300mb:

[root@docker-node1 ~]#cd /sys/fs/cgroup/memory/docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616/
[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]# 
cat memory.memsw.limit_in_bytes
209715200

[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]# echo 314572800 > memory.memsw.limit_in_bytes
[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]# cgexec -g memory:docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=300

(4)、限制docker的磁盘io

[root@docker-node1 ~]# docker run -it --rm --device-write-bps /dev/nvme0n1:30M ubuntu
root@452768b7f1e0:/# dd if=/dev/zero of=bigfile
root@452768b7f1e0:/#  dd if=/dev/zero of=bigfile bs=1M count=100
root@452768b7f1e0:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct

七、docker的安全加固

1、docker默认隔离性

可以看到虽然限制了容器200m的内存,但是内存资源并没有完全隔离。

2、解决默认隔离性问题

LXCFS 是一个为 LXC(Linux Containers)容器提供增强文件系统功能的工具。

LXCFS 可以使容器内的进程看到准确的 CPU、内存和磁盘 I/O 等资源使用信息。在没有 LXCFS 时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和管理。

安装lxcfs

[root@docker-node1 ~]# cd /mnt/
[root@docker-node1 mnt]# ls
hgfs                          lxc-libs-4.0.12-1.el9.x86_64.rpm
lxcfs-5.0.4-1.el9.x86_64.rpm  lxc-templates-4.0.12-1.el9.x86_64.rpm
[root@docker-node1 mnt]# dnf install *.rpm

运行lxcfs解决隔离性问题:

[root@docker-node1 ~]# lxcfs /var/lib/lxcfs &

开启容器并指定内存:

docker run  -it --name test -m 256m -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw -v /var/lib/lxcfs/proc/stat:/proc/stat:rw -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw ubuntu

可以看到指定的内存为256m,容器显示的内存就为256m。

4、容器特权

5、容器白名单

八、容器编排工具Docker Compose

编辑vim配置文件:

vim ~/.vimrc

1、基础操作

[root@docker-node1 ~]# mkdir test
[root@docker-node1 test]# cd test/
#编辑yml文件
[root@docker-node1 test]# vim docker-compose.yml
#启动服务
[root@docker-node1 test]# docker compose up -d
[+] Running 3/3
 ✔ Network test_default   Created                                    0.2s 
 ✔ Container test-web-1   Started                                    1.6s 
 ✔ Container test-test-1  Started                                    1.5s 
[root@docker-node1 test]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS         PORTS     NAMES
1b571c4c09aa   nginx:latest   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds   80/tcp    test-web-1

[root@docker-node1 test]# cp docker-compose.yml new-compose.yml
[root@docker-node1 test]# rm -rf docker-compose.yml 
[root@docker-node1 test]# vim new-compose.yml 

#可以使用-f 来指定yml文件
[root@docker-node1 test]# docker compose -f new-compose.yml up -d
[+] Running 2/2
 ✔ Container test-test-1  Started                                    1.1s 
 ✔ Container test-web-1   Started 
#停止正在运行的服务
[root@docker-node1 test]# docker compose stop
[+] Stopping 2/2
 ✔ Container test-web-1   Stopped                                    0.1s 
 ✔ Container test-test-1  Stopped                                    0.0s 
#重启服务
[root@docker test]# docker compose restart
#停止并删除配置文件中定义的所有服务以及相关的网络和存储卷。
[root@docker test]# docker compose down
#查看状态
[root@docker-node1 test]# docker compose ps
NAME         IMAGE          COMMAND                   SERVICE   CREATED              STATUS          PORTS
test-web-1   nginx:latest   "/docker-entrypoint.…"   web       About a minute ago   Up 11 seconds   80/tcp

2、构建和重新构建服务

编辑构建docker的文件:

[root@docker-node1 test]# vim Dockerfile
[root@docker-node1 test]# vim new.Dockerfile

写重新构建的文件:在之前test1、test2的基础上重新构建

[root@docker-node1 test]# vim docker-compose.yml 

构建生效:

#build
[root@docker-node1 test]# docker compose -f docker-compose.yml  build#构建
services中所有
[root@docker test]# docker compose -f test.yml build test1 #构建
services中的test1

可以看到构建的新镜像:test1、test2

开启容器:可以看到旧的test1、test2构建时创建的文件

以上是构建好镜像后手动开启容器。

自动开启容器:

# --build
[root@docker test]# docker compose -f docker-compose.yml up -d #会去仓库拉去镜
像

[root@docker test]# docker compose -f docker-compose.yml up --build #会先构建镜像后
启动容器

可以看到自动开启容器:

3、其他操作

  • docker-compose exec :
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose -f docker-compose.yml up -d
#在正在运行的服务容器中执行命令
[root@docker-node1 test]# docker compose -f docker-compose.yml  exec test1 sh
/ # touch newfile
/ # ls
bin      etc      lib      newfile  root     tmp      var
dev      home     lib64    proc     sys      usr
/ #

  • docker-compose pull :

拉取配置文件中定义的服务所使用的镜像。

[root@docker test]# docker compose -f docker-compose.yml pull
[+] Pulling 2/2
✔ test Pulled
✔ ec562eabd705 Pull complete
  • docker-compose config :

验证并查看解析后的 Compose 文件内容

[root@docker-node1 test]# docker compose config 
name: test
services:
  test1:
    command:
      - /bin/sh
      - -c
      - sleep 3000
    container_name: busybox1
    image: busybox:latest
    networks:
      default: null
    restart: always
networks:
  default:
    name: test_default

4、Docker Compose 的yml文件

(1)、服务

#服务名称(service1_name/service2_name 等):每个服务在配置文件中都有一个唯一的名称,用于在命令行和其他部分引用该服务。

services:
web:
# 服务1的配置
mysql:
# 服务2的配置
#镜像(image):
#指定服务所使用的 Docker 镜像名称和标签。例如, image: nginx:latest 表示使用 nginx镜像的最新版本

services:
  web:
    images:nginx
  mysql:
    images:mysql:5.7
#将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。例如, -"8080:80" 表示将主机的 8080 端口映射到容器内部的 80 端口。

services:
  web:
    image: nginx:latest
    container_name: nginx1 #指定容器名称
    restart: always #docekr容器自动启动
    expose:
        - 1234 #指定容器暴露那些端口,些端口仅对链接的服务可见,不会映射到主机的端口
    ports:
        - "80:8080"
#环境变量(environment):为容器设置环境变量,可以在容器内部的应用程序中使用。例如, VAR1: value1 设置环境变量 VAR1 的值为 value1

services:
  web:
    image: mysql:5.7
    container_name: mysql1
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: gyj
#存储卷(volumes):将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。例如, -
/host/data:/container/data 将主机上的 /host/data 目录挂载到容器内的/container/data 路径。

services:
  test:
    image: busybox
    command: ["/bin/sh","-c","sleep 3000"]
    restart: always
    container_name: busybox1
    volumes:
        - /etc/passwd:/tmp/passwd:ro   #只读挂在本地文件到指定位置
#网络(networks):将服务连接到特定的网络,以便不同服务的容器可以相互通信

services:
  web:
    image: nginx
    container_name: webserver
    network_mode: bridge  #使用本机自带bridge网络

services:
  test:
    image: busybox
    container_name: webserver
    command: ["/bin/sh","-c","sleep 10000"]

  #network_mode: mynet2

  networks:
    - mynet1
    - mynet2
  networks:
    mynet1:
      driver: bridge
    mynet2:
      driver: bridge
#命令(command):覆盖容器启动时默认执行的命令。例如, command: python app.py 指定容器启动时运行
python app.py 命令

[root@docker test]# vim busybox.yml

services:
  web:
    image: busybox
    container_name: busybox
    #network_mode: mynet2
    command: ["/bin/sh","-c","sleep10000000"]

(2)、网络

  • 定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。
  • 默认情况下docker compose 在执行时会自动建立网路
services:
    test:
        image: busybox1
        command: ["/bin/sh","-c","sleep 3000"]
        restart: always
        network_mode: default
        container_name: busybox
    test1:
        image: busybox2
        command: ["/bin/sh","-c","sleep 3000"]
        restart: always
        container_name: busybox1
        networks:
            - mynet1
    test3:
        image: busybox3
        command: ["/bin/sh","-c","sleep 3000"]
        restart: always
        container_name: busybox1
        networks:
            - mynet1
networks:
    mynet1:
        driver: bridge #使用桥接驱动,也可以使用macvlan用于跨主机连接
    default:
        external: true #不建立新的网络而使用外部资源
        name: bridge   #指定外部资源网络名字
    mynet2:
        ipam:
        driver: default
        config:
            - subnet: 172.28.0.0/16
            gateway: 172.28.0.254

(3)、存储卷

services:
    test:
    image: busybox
    command: ["/bin/sh","-c","sleep 3000"]
    restart: always
    container_name: busybox1
    volumes:
        - data:/test #挂在data卷
        - /etc/passwd:/tmp/passwd:ro #只读挂在本地文件到指定位置

volumes:
    data:
    name: timinglee #指定建立卷的名字

九、利用docker编排完成haproxy和nginx负载均衡架构

1、只下载haproxy,找出haproxy的配置文件,编辑配置文件

#只下载不安装haproxy
[root@docker-node1 ~]# dnf install haproxy -y --downloadonly --downloaddir=/mnt
#解压文件并输出为目录,-id:i是输出,d是目录
[root@docker-node1 mnt]# rpm2cpio haproxy-2.4.22-1.el9.x86_64.rpm | cpio -id

2、编辑docker compose容器编排文件

[root@docker-node1 ~]# vim haproxy.yml

3、启动容器

[root@docker-node1 ~]# docker compose -f /root/haproxy.yml up -d

4、查看是否启动

5、写入网页内容

从配置文件可以看到,在主机的/var/lib/docker/volumes/data_web目录下,有data_web1和data_web2,这两个文件挂载的是nginx容器的网站首发内容页,所以在data_web1、data_web2这两个目录下写入网站首页内容。

6、测试

haproxy用的是轮询调度算法

删除镜像、加速器、volume

ldd /usr/local/nginx/sbin/nginx nginx运行时必须调用的模块

标签: docker 容器 运维

本文转载自: https://blog.csdn.net/m0_58140853/article/details/141597983
版权归原作者 暗中讨饭^_^ 所有, 如有侵权,请联系我们删除。

“一篇文章教你玩转Docker!”的评论:

还没有评论