一篇文章教你玩转Docker!

暗中讨饭^_^ 2024-10-24 12:37:03 阅读 100

目录

一、基础操作

二、构建镜像

1、参数示例及使用方法

2、Docker构建实例

3、镜像优化示例

三、docker镜像仓库管理

1、docker hub

2、搭建私有仓库

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

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

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

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

四、docker的网络

1、dacker的原生网络

(1)、bridge

(2)、host

(3)、none

2、docker的自定义网络

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

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

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

4、容器内外网的访问

(1)、容器访问外网

(2)、外网访问容器

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

五、docker的数据卷管理

1、bind mount数据卷

2、docker managed数据卷

​编辑

3、数据卷容器

六、docker的安全优化

1、docker的资源限制

(1)、限制cpu的使用量

(2)、限制cpu的优先级

(3)、限制内存使用

(4)、限制docker的磁盘io

七、docker的安全加固

1、docker默认隔离性

2、解决默认隔离性问题

4、容器特权

5、容器白名单

八、容器编排工具Docker Compose

1、基础操作

2、构建和重新构建服务

3、其他操作

4、Docker Compose 的yml文件

(1)、服务

(2)、网络

(3)、存储卷

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

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

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

3、启动容器

4、查看是否启动

5、写入网页内容

6、测试


准备工作:

搭建本地网络源:

<code>cd /etc/yum.repos.d/

vim docker-ce.repo

一、基础操作

<code>#拉取镜像

[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

镜像

eg

FROM busybox:version

COPY

复制文件

eg

COPY 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

指定环境变量

eg

ENV FILENAME test

EXPOSE

暴漏容器端口

eg

EXPOSE 80

VOLUME

申明数据卷,通常指数据挂载点

eg

VOLUME [“/var/www/html”]

WORKDIR

切换路径

eg

WORKDIR /mnt

RUN

在容器中运行的指令

eg: touch file

CMD

在启动容器时自动运行动作可以被覆盖

eg

CMD echo $FILENAME

会调用

shell

解析

eg

CMD [“/bin/sh”,”-c”,“echo $FILENAME”]

不调用

shell

解析

ENTRYPOINT

CMD

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

<code>[root@decker-node1 ~]# cd docker/

[root@decker-node1 docker]# touch dockerfile

[root@decker-node1 docker]# vim dockerfile

volume:

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

2、Docker构建实例

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

<code>[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

编写构建文件:

开始构建: 

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

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

dnf install httpd -y

#配置文件的端口改为8888

systemctl restart httpd

新加cdroom:

挂载本地软件仓库sr1: 

开启centos7容器:

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

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

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

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

 修改构建文件:

继续构建nginx镜像:

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

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

3、镜像优化示例

缩减镜像层:

<code>[root@decker-node1 docker]# vim dockerfile

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

 多阶段构建:

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

使用最精简镜像

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

<code>[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)、搭建简单无加密私有仓库

下载镜像:

<code>[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

上传:

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

查看镜像上传:

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

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

生成认证证书和key

<code>#删除配置文件的非加密配置

[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读取证书:

<code>[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

上传:

<code>[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加密):

<code>[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:

<code>[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:

<code>[root@decker-node1 harbor]# docker compose stop

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

本地解析:

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

 

新建项目:

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

<code>#登录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:

<code>#一键加载镜像

#所有的镜像文件在/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不同,会导致容器之间通讯出现问题。

<code>

[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)、容器用不同的网络栈

<code>#创建两个自定义桥接网络

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

2a79172a5fe1a4b433c3daf4bdefaabf89b0a656aa5e7a07c007ae6a05a7b078

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

a79928a1c7ec8d4037863138b02a5fb967254ee3a560388572b0b16fd6ae0745

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

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

<code>#将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:

<code>[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,更安全。

<code>[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' \code>

> --network container:mysqladmin \

> mysql:5.7

登录:浏览器输入172.25.254.100

在mysql容器内执行命令:

<code>[root@docker-node1 ~]# docker exec -it mysql bash

bash-4.2#

也可以用phpmyadmin管理数据库。

4、容器内外网的访问

(1)、容器访问外网

(2)、外网访问容器

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

macvlan

在两台

docker

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

<code>[root@docker-node1 ~]# ip link set eth1 promisc on

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

两主机添加macvlan网络:

<code>[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 选项指定路径。

<code>[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中

<code>[root@docker-node1 ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='gyj' mysql:5.7code>

[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

中一种特殊的容器,主要用于方便地在多个容器之间 共享数据卷。

<code>#建立数据卷容器

[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的优先级

<code>[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)、限制内存使用

上传工具:

<code>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:

<code>[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

<code>[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

<code>[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配置文件:

<code>vim ~/.vimrc

1、基础操作

<code>[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

<code>[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的基础上重新构建 

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

构建生效: 

<code>#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构建时创建的文件

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

自动开启容器:

<code># --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 :

<code>[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

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

<code>[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容器编排文件

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

3、启动容器

<code>[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运行时必须调用的模块



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。