Docker镜像

本文详细介绍了Docker镜像的下载、安装、分层结构及构建,强调了Dockerfile的使用和镜像优化。此外,还探讨了私有仓库的建立、镜像加速器配置、企业级仓库Harbor的构建,以及Docker网络配置。在安全方面,讨论了容器资源控制、安全加固策略和Docker安全工具。最后,简述了Docker Machine、Docker Compose和Docker Swarm在集群管理中的作用。

目录

一、Docker镜像下载与安装

二、 镜像的分层结构

三、 镜像的构建

docker commit

创建Dockerfile

Dockerfile常用命令

FROM

RUN

COPY

ADD

ENV

EXPOSE

VOLUME

CMD 与 ENTRYPOINT

四、创建nginx镜像及优化

封装镜像

镜像的优化

减少镜像的层数

使用多阶段构建镜像

选择最精简的基础镜像

五、建立私有仓库

六、配置镜像加速器

阿里云加速器

官方加速器

七、构建企业级仓库harbor

八、Docker 原生网络

bridge

host

none

九、Docker 自定义网络

十、Docker容器通信

--network

容器访问外网

外网访问容器

十一、跨主机容器网络

macvlan网络方案实现

十二、Docker数据卷

bind mount

docker managed volume

卷插件

convoy

十三、Docker安全

Docker安全简介

容器资源控制

CPU限额

Block IO限制

十四、Docker安全加固

LXCFS

设置特权级运行的容器: --privileged=true

设置容器白名单: --cap-add

安全加固的思路

保证镜像的安全

保证容器的安全

Docker安全的顶尖开源工具

十五、Docker Machine

十六、Docker Compose

Docker Compose简介

Docker Compose实践

十七、Docker Swarm


Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用

cgroup 实现资源限制

一、Docker镜像下载与安装

下载地址:docker-ce镜像-docker-ce下载地址-docker-ce安装教程-阿里巴巴开源镜像站

配置源

[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# curl https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o docker-ce.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2081  100  2081    0     0   6282      0 --:--:-- --:--:-- --:--:--  6287
[root@server1 yum.repos.d]# vim docker-ce.repo

 安装centOS源

centos镜像-centos下载地址-centos安装教程-阿里巴巴开源镜像站

[root@server1 yum.repos.d]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2523  100  2523    0     0   8976      0 --:--:-- --:--:-- --:--:--  8978
[root@server1 yum.repos.d]# vim CentOS-Base.repo 

[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/extras/$basearch/
gpgcheck=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

只激活[extras]
其他都enabled=0

安装docker-ce

[root@server1 yum.repos.d]# yum install -y docker-ce

[root@server1 yum.repos.d]# systemctl enable --now docker
[root@server1 yum.repos.d]# docker info

查看有警告

 是网桥有问题,配置网桥

[root@server1 yum.repos.d]# cd /etc/docker/
[root@server1 docker]# sysctl -a |grep  bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 0
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth1.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"

[root@server1 docker]# vim /etc/sysctl.d/docker.conf

net.bridge.bridge-nf-call-iptables = 1

[root@server1 docker]# sysctl --system

 测试:下载容器库中的数据

[root@server1 ~]# docker pull yakexi007/game2048
Using default tag: latest
latest: Pulling from yakexi007/game2048
534e72e7cedc: Pull complete 
f62e2f6dfeef: Pull complete 
fe7db6293242: Pull complete 
3f120f6a2bf8: Pull complete 
4ba4e6930ea5: Pull complete 
Digest: sha256:8a34fb9cb168c420604b6e5d32ca6d412cb0d533a826b313b190535c03fe9390
Status: Downloaded newer image for yakexi007/game2048:latest
docker.io/yakexi007/game2048:latest
[root@server1 ~]# docker run -d --name demo -p 80:80  yakexi007/game2048
dcda3e27fc9e553043aeee96971547d1a2ac92ef897a1871a4e1bd435a8a78cf

访问172.25.6.1

 删除

[root@server1 ~]# docker ps
CONTAINER ID   IMAGE                COMMAND                  CREATED              STATUS              PORTS                                        NAMES
dcda3e27fc9e   yakexi007/game2048   "/bin/sh -c 'sed -i …"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp, 443/tcp   demo
[root@server1 ~]# docker rm -f demo
demo

安装 busybox


[root@server1 ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
5cc84ad355aa: Pull complete 
Digest: sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@server1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED       SIZE
busybox              latest    beae173ccac6   4 days ago    1.24MB
yakexi007/game2048   latest    19299002fdbe   5 years ago   55.5MB
[root@server1 ~]# docker run -it --name demo busybox  这里输入命令,ctrl d退出
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # touch file
/ # ls
bin   dev   etc   file  home  proc  root  sys   tmp   usr   var
/ # rm -f file
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
[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
ad118e314332   busybox   "sh"      54 seconds ago   Exited (0) 29 seconds ago             demo
[root@server1 ~]# docker rm demo 删除进程
demo
[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

二、 镜像的分层结构

  • 共享宿主机的kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源

  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127层

[root@server1 ~]# docker start demo
demo
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
bbb644964514   busybox   "sh"      4 minutes ago   Up 6 seconds             demo
[root@server1 ~]# docker attach demo
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # touch file1
/ # touch file2
/ # touch file3
/ # ls
bin    etc    file2  home   root   tmp    var
dev    file1  file3  proc   sys    usr
/ # read escape sequence  ##ctrl q p后台运行

三、 镜像的构建

docker commit

docker commit 构建新镜像三部曲

  • 运行容器
  • 修改容器
  • 将容器保存为新的镜像

缺点:
效率低、可重复性弱、容易出错
使用者无法对镜像进行审计,存在安全隐患

[root@server1 ~]# docker commit demo demo:v1  提交镜像
sha256:c7eba38f8d62ca0b8c5968d0676fbe96eafe33fd4b87700b08c531e164290835
[root@server1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
demo                 v1        c7eba38f8d62   25 seconds ago   1.24MB
busybox              latest    beae173ccac6   4 days ago       1.24MB
yakexi007/game2048   latest    19299002fdbe   5 years ago      55.5MB
[root@server1 ~]# docker history demo:v1
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
c7eba38f8d62   44 seconds ago   sh                                              51B       
beae173ccac6   4 days ago       /bin/sh -c #(nop)  CMD ["sh"]                   0B        
<missing>      4 days ago       /bin/sh -c #(nop) ADD file:6db446a57cbd2b7f4…   1.24MB    
[root@server1 ~]# docker history busybox:latest
IMAGE          CREATED      CREATED BY                                      SIZE      COMMENT
beae173ccac6   4 days ago   /bin/sh -c #(nop)  CMD ["sh"]                   0B        
<missing>      4 days ago   /bin/sh -c #(nop) ADD file:6db446a57cbd2b7f4…   1.24MB    
[root@server1 ~]# docker rm demo
demo
[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@server1 ~]# docker run -it --rm demo:v1
/ # ls
bin    etc    file2  home   root   tmp    var
dev    file1  file3  proc   sys    usr
/ # 
[root@server1 ~]# docker run -it --rm busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var

但这样提交看不到操作记录

创建Dockerfile

我们可以用创建Dockerfile的方法构建镜像

[root@server1 ~]# mkdir docker
[root@server1 ~]# cd docker/
[root@server1 docker]# vim Dockerfile

FROM busybox
RUN touch file1 file2 file3
~                                  

[root@server1 docker]# docker build -t demo:v2 .
[root@server1 docker]# docker images
[root@server1 docker]# docker history demo:v2

Dockerfile常用命令

FROM

指定base镜像,如果本地不存在会从远程仓库下载

RUN

在容器中运行命令并创建新的镜像层,常用于安装软件包

[root@server1 docker]# vim Dockerfile

FROM busybox
RUN touch file1 file2 file3
CMD echo "hello world"
[root@server1 docker]# docker build -t demo:v3 .
[root@server1 docker]# docker run --rm demo:v3
hello world

COPY

把文件从build context复制到镜像
支持两种形式:COPY src dest 和 COPY ["src", "dest"]
src必须指定build context中的文件或目录

[root@server1 docker]# vim Dockerfile
[root@server1 docker]# echo www.westos.org > index.html
[root@server1 docker]# ls
Dockerfile  index.html   
[root@server1 docker]# docker build -t demo:v4 .
[root@server1 docker]# docker history demo:v4
[root@server1 docker]# docker run --rm demo:v4 cat /index.html

 

ADD

用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像

[root@server1 docker]# vim Dockerfile
ADD nginx-1.20.2.tar.gz / 
[root@server1 docker]# docker build -t demo:v5 .
[root@server1 docker]# docker run --rm demo:v5 ls /

ENV

设置环境变量,变量可以被后续的指令使用

[root@server1 docker]# vim Dockerfile
ENV hostname server1
CMD echo $hostname

[root@server1 docker]# vim Dockerfile
[root@server1 docker]# docker build -t demo:v6 .
[root@server1 docker]# docker run --rm demo:v6

EXPOSE

如果容器中运行应用服务,可以把服务端口暴露出去

EXPOSE 80
[root@server1 docker]# docker run -d --name demo -p 80:8080 yakexi007/mario
[root@server1 docker]# docker ps
[root@server1 docker]# docker port demo

 网桥会自动分配一个ip

 

VOLUME

申明数据卷,通常指定的是应用的数据挂在点

VOLUME ["/data"]
[root@server1 docker]# docker build -t demo:v7 .
[root@server1 docker]# docker history demo:v7
[root@server1 docker]# docker run -it --rm demo:v7 sh
/ # ls
bin           etc           file3         nginx-1.20.2  sys           var
data          file1         home          proc          tmp
dev           file2         index.html    root          usr
/ # cd data
/data # touch file
/data # ls
file
/data # rm -f file
/data # cp /index.html .
/data # ls
index.html
/data # 
[root@server1 docker]# docker inspect 07167cc0ecac 
[root@server1 docker]# cd /var/lib/docker/volumes/96113ea9cc0f4343d0491ea6cf4e338d8a913a37550e6205d85696cc3fddf139/_data  ##容器和此目录是互通的
[root@server1 _data]# ls
index.html
[root@server1 _data]# rm -f index.html 
[root@server1 _data]# cp /etc/passwd .
[root@server1 _data]# ls
passwd
[root@server1 _data]# docker attach 07167cc0ecac
/data # ls
passwd

 查看信息可以查看到所关联目录

CMD 与 ENTRYPOINT

这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

CMD ["/bin/echo", "$hostname"]
[root@server1 docker]# docker build -t demo:v8 .
[root@server1 docker]# docker run  --rm demo:v8
$hostname
[root@server1 docker]# docker rmi demo:v8

CMD无法识别echo

 修改一下

CMD ["/bin/sh","-c","echo $hostname"]
[root@server1 docker]# docker run  --rm demo:v8
server1

Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数。

ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
~        

[root@server1 docker]# docker build -t demo:v9 .

[root@server1 docker]# docker run  --rm demo:v9
hello world
[root@server1 docker]# docker run  --rm demo:v9 linux
hello linux
[root@server1 docker]# docker run  --rm demo:v9 linux redhat
hello linux redhat

四、创建nginx镜像及优化

[root@server1 ~]# docker images | grep demo | awk '{system("docker rmi "$1":"$2"")}'
删除之前创建的

[root@server1 ~]# docker pull centos
[root@server1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED        SIZE
busybox              latest    beae173ccac6   4 days ago     1.24MB
centos               latest    5d0da3dc9764   3 months ago   231MB
yakexi007/game2048   latest    19299002fdbe   5 years ago    55.5MB
yakexi007/mario      latest    9a35a9e43e8c   6 years ago    198MB
[root@server1 ~]# docker history centos:latest 
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
5d0da3dc9764   3 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]      ##如果有cmd运行时后面可以不加sh,否则要加sh       0B        
<missing>      3 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      3 months ago   /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0…   231MB 

配置yum源

[root@server1 docker]# docker run -it --name demo centos
[root@ea60710ad825 /]# cd /etc/yum.repos.d
[root@ea60710ad825 yum.repos.d]# rm -fr *
[root@ea60710ad825 yum.repos.d]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
[root@ea60710ad825 yum.repos.d]# ls
CentOS-Base.repo
[root@ea60710ad825 yum.repos.d]# vi CentOS-Base.repo

需要[AppStream]和[base]

 安装nginx

docker cp nginx-1.20.2.tar.gz demo:/ ##复制压缩包到容器
[root@server1 docker]# docker run -it --name demo centos
[root@ea60710ad825 /]# tar zxf nginx-1.20.2.tar.gz
[root@ea60710ad825 /]# cd /etc/yum.repos.d
[root@ea60710ad825 yum.repos.d]# rm -fr *
[root@ea60710ad825 yum.repos.d]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
[root@ea60710ad825 yum.repos.d]# ls
CentOS-Base.repo
[root@ea60710ad825 yum.repos.d]# vi CentOS-Base.repo

需要[AppStream]和[base]

[root@ea60710ad825 yum.repos.d]# yum repolist
Failed to set locale, defaulting to C.UTF-8
repo id                    repo name
AppStream                  CentOS-8 - AppStream - mirrors.aliyun.com
base                       CentOS-8 - Base - mirrors.aliyun.com

[root@ea60710ad825 yum.repos.d]# yum install -y gcc pcre-devel openssl-devel make

[root@ea60710ad825 nginx-1.20.2]# vi auto/cc/gcc   
# debug
#CFLAGS="$CFLAGS -g"

[root@ea60710ad825 nginx-1.20.2]# ./configure --with-http_ssl_module

[root@ea60710ad825 nginx-1.20.2]# make

[root@ea60710ad825 nginx-1.20.2]# make install 
[root@ea60710ad825 sbin]# ./nginx 
[root@ea60710ad825 sbin]# ps ax
  PID TTY      STAT   TIME COMMAND
    1 pts/0    Ss     0:00 /bin/bash
 4926 ?        Ss     0:00 nginx: master process ./nginx
 4927 ?        S      0:00 nginx: worker process
 4928 pts/0    R+     0:00 ps ax

封装镜像

[root@server1 docker]# vim Dockerfile 

FROM centos
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
RUN yum install -y gcc pcre-devel openssl-devel make
ADD nginx-1.20.2.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.2
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module
RUN make
RUN make install
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]


[root@server1 docker]# docker build -t webserver:v1 .
[root@server1 docker]# docker run -d --name demo webserver:v1
415d680eeb95953c79d959f14fb1ecd68b90e8d6bf8efd0e0e57ca552013b706

 测试

镜像的优化

  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 注意优化网络请求
  • 尽量去用构建缓存
  • 使用多阶段构建镜像

减少镜像的层数

FROM centos
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
RUN yum install -y gcc pcre-devel openssl-devel make
ADD nginx-1.20.2.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.2
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module && make && make install && rm -fr /mnt/nginx-1.20.2 && yum clean
 all
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
~                   

[root@server1 docker]# docker build -t webserver:v2 .

 变化不是很大

使用多阶段构建镜像

 FROM centos as build
RUN rm -f /etc/yum.repos.d/*.repo
COPY CentOS-Base.repo /etc/yum.repos.d/
RUN yum install -y gcc pcre-devel openssl-devel make
ADD nginx-1.20.2.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.2
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module && make && make install && rm -fr /mnt/nginx-1.20.2 && yum clean all

FROM centos
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

[root@server1 docker]# docker build -t webserver:v3 .

[root@server1 docker]# docker run -it --rm webserver:v3 bash
[root@de006fcab9e1 /]# ldd /usr/local/nginx/sbin/nginx 
	linux-vdso.so.1 (0x00007ffff2dc2000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f3786c42000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3786a22000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f37867f2000)
	libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f378657a000)
	libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007f37862e2000)
	libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f3785dfa000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f3785be2000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f378581a000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3786e4a000)

缩减很多

选择最精简的基础镜像

可以在官网中寻找

GitHub: Where the world builds software · GitHub

[root@server1 docker]# vim Dockerfile


FROM nginx:1.18.0 as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE

RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /usr/sbin/nginx-debug /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

FROM gcr.io/distroless/base-debian10

COPY --from=base /opt /

EXPOSE 80 443

ENTRYPOINT ["nginx", "-g", "daemon off;"]           

需要拉取nginx和依赖

[root@server1 ~]# docker load -i base-debian10.tar
[root@server1 docker]# docker pull nginx:1.18
[root@server1 docker]# docker build -t webserver:v4 .

可以看到缩减很多, 所以在实际构建中尽量选择最精简的base镜像

测试

[root@server1 docker]# docker inspect demo1
[root@server1 docker]# curl 172.17.0.3

五、建立私有仓库

删除不用的容器 docker images | grep webserver | awk '{system("docker rmi "$1":"$2"")}'

我们先下载registry镜像

[root@server1 ~]# docker pull registry
[root@server1 ~]# docker history registry:latest 查看到5000端口
[root@server1 ~]# docker run -d --name registry -p 5000:5000 registry  运行容器
[root@server1 ~]# docker ps
[root@server1 ~]# docker tag busybox:latest localhost:5000/busybox:latest 设置标签
[root@server1 ~]# docker images

 

 上传至仓库

[root@server1 ~]# docker push localhost:5000/busybox:latest

删除之前拉取的,重新从私有仓库拉取

[root@server1 ~]# docker rmi busybox:latest

[root@server1 ~]# docker rmi localhost:5000/busybox

 [root@server1 ~]# docker pull localhost:5000/busybox:latest

搭建仓库帮助文档

Deploy a registry server | Docker Documentation

证书认证

Test an insecure registry | Docker Documentation

需要安装openssl11

[root@server1 ~]# mkdir certs

[root@server1 ~]# openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/westos.org.key -addext "subjectAltName = DNS:reg.westos.org" -x509 -days 365 -out certs/westos.org.crt 填写证书内容

Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shaanxi
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) []:reg.westos.org
Email Address []:root@westos.org

运行

Deploy a registry server | Docker Documentation

[root@server1 ~]# docker run -d  --restart=always --name registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt  -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key  -p 443:443 registry

[root@server1 ~]# vim /etc/hosts/ ##添加地址解析
172.25.6.1      server1 reg.westos.org

[root@server1 ~]# docker tag localhost:5000/busybox:latest reg.westos.org/busybox:latest
[root@server1 ~]# docker push reg.westos.org/busybox:latest

此时会出现错误

 证书有问题,我们需要将证书放在指定目录下

[root@server1 ~]# cd /etc/docker
[root@server1 docker]# ls
daemon.json  key.json
[root@server1 docker]# mkdir certs.d
[root@server1 docker]# cd certs.d/
[root@server1 certs.d]# mkdir reg.westos.org
[root@server1 certs.d]# cd reg.westos.org/
[root@server1 reg.westos.org]# cp /root/certs/westos.org.crt ca.crt
[root@server1 reg.westos.org]# ls
ca.crt
[root@server1 reg.westos.org]# pwd
/etc/docker/certs.d/reg.westos.org
[root@server1 ~]# docker push reg.westos.org/busybox:latest

重新上传成功

 [root@server1 ~]# yum install -y httpd-tools

添加用户和密码

[root@server1 ~]# htpasswd -cB auth/htpasswd admin
New password: 
Re-type new password: 
Adding password for user admin
[root@server1 ~]# htpasswd -B auth/htpasswd xmm
New password: 
Re-type new password: 
Adding password for user xmm
[root@server1 ~]# cat auth/htpasswd 


 

 再次运行

 清理不需要的倦

[root@server1 ~]# docker volume ls
DRIVER    VOLUME NAME
local     1bbb07cd9402d2a3fd791018a36d5c0ee61abb20243e883f07e7638792712e81
local     25a81c8b9a4def461375201a7717551246f07a6c9d10fc22e209d62aa96cce6c
local     003545d2afc68f345bbe013328fd098463f0ada38522e770afd42e47a4b60fe6
[root@server1 ~]# docker volume prune

 再次push会出现错误

 需要登陆用户

[root@server1 ~]# docker login reg.westos.org
Username: admin
Password:

 再次push成功

 测试

[root@server1 ~]# curl -u admin:westos -k https://reg.westos.org/v2/_catalog
{"repositories":["busybox"]}

registry工作原理

index服务主要提供镜像索引以及用户认证的功能。当下载一个镜像的时候,首先会去index服务上做认证,然后查找镜像所在的registry的地址并放回给docker客户端,docker客户 端再从registry下载镜像,在下载过程中registry会去index校验客户端token的合法性,不同镜像可以保存在不同的registry服务上,其索引信息都放在index服务上。

六、配置镜像加速器

阿里云加速器

阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

每个账户加速器地址不同

用户中心——工作台——镜像工具——镜像加速器

[root@server1 ~]# cd /etc/docker/
[root@server1 docker]# vim daemon.json

[root@server1 docker]# systemctl daemon-reload
[root@server1 docker]# systemctl restart docker
[root@server1 docker]# docker info

官方加速器

同理,只是地址不同

[root@server1 docker]# vim daemon.json

七、构建企业级仓库harbor

[root@server1 ~]# docker rm -f registry 
[root@server1 ~]# mv docker-compose-linux-x86_64-v2.0.1 /usr/local/bin/docker-compose
[root@server1 ~]# chmod +x /usr/local/bin/docker-compose
[root@server1 ~]# tar zxf harbor-offline-installer-v2.3.4.tgz

[root@server1 ~]# cd harbor/
[root@server1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@server1 harbor]# vim harbor.yml  ##更改配置文件

hostname: reg.westos.org
certificate: /data/certs/westos.org.crt
private_key: /data/certs/westos.org.key

harbor_admin_password: westos

 建立证书目录

[root@server1 harbor]# mkdir /data
[root@server1 harbor]# cd
[root@server1 ~]# mv certs/ /data/
[root@server1 ~]# cd /data
[root@server1 data]# ls
certs
[root@server1 data]# cd certs/
[root@server1 certs]# ls
westos.org.crt  westos.org.key

安装

[root@server1 harbor]# mkdir /var/log/harbor/
[root@server1 harbor]# ./install.sh

 访问172.25.6.1登陆harbor

 docker-compose ps只能在 docker-compos.yml所在目录中使用

 重新登陆一下

 重新上传

[root@server1 ~]# docker tag reg.westos.org/busybox:latest reg.westos.org/library/busybox:latest
[root@server1 ~]# docker push reg.westos.org/library/busybox:latest 
[root@server1 ~]# docker tag nginx:latest reg.westos.org/library/nginx:latest
[root@server1 ~]# docker push reg.westos.org/library/nginx

可以在前端看到上传的镜像

 新开一台主机

[root@server1 docker]# scp -r certs.d/ server2:/etc/docker/

[root@server1 docker]# scp  daemon.json server2:/etc/docker/

[root@server2 ~]# vim /etc/hosts
172.25.6.1      server1 reg.westos.org
[root@server2 docker]# vim  daemon.json
[root@server2 docker]# systemctl daemon-reload
[root@server2 docker]# systemctl reload docker

拉取镜像,可以发现是从仓库中拉取的

[root@server2 docker]# docker pull nginx

 安装harbor一些插件

[root@server1 harbor]# docker-compose stop

[root@server1 harbor]# docker-compose down
[root@server1 harbor]# ./install.sh --with-notary --with-trivy --with-chartmuseum

之后我们可以进行扫描,扫描的网速如果太慢,可以直接将离线库解压到/data/trivy-adapter/trivy/db 注意权限

[root@server1 db]# chown 10000.10000 metadata.json
[root@server1 db]# chown 10000.10000 trivy.db
[root@server1 trivy]# chown 10000.10000 db

 扫描完成

内容信任开启后,其他主机没有签名无法从仓库下载 

我们需要加入认证

[root@server1 ~]# cd .docker/
[root@server1 .docker]# ls
config.json
[root@server1 .docker]# mkdir tls/reg.westos.org:4443 -p
[root@server1 .docker]# cd tls/
[root@server1 tls]# ls
reg.westos.org:4443
[root@server1 tls]# cd reg.westos.org\:4443/
[root@server1 reg.westos.org:4443]# cp /etc/docker/certs.d/reg.westos.org/ca.crt .
[root@server1 reg.westos.org:4443]# ls
ca.crt

[root@server1 reg.westos.org:4443]# export DOCKER_CONTENT_TRUST=1
[root@server1 reg.westos.org:4443]# export DOCKER_CONTENT_TRUST_SERVER=https://reg.westos.org:4443

[root@server1 ~]# docker push reg.westos.org/library/nginx:latest 

[root@server1 ~]# docker tag nginx:1.18 reg.westos.org/library/nginx:1.18
[root@server1 ~]# docker push reg.westos.org/library/nginx:1.18 

看签名为绿色,此主机2可以拉取

 [root@server2 docker]# docker pull nginx拉取之后可以在日志看到记录

八、Docker 原生网络

bridge

docker安装时会创建一个名为docker0的linux bridge,新建的容器会自动桥接到这个接口

[root@server2 docker]# yum install -y bridge-utils.x86_64 

[root@server2 docker]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02426c2351ec	no		
[root@server2 docker]# docker run -d --name demo nginx
[root@server2 docker]# docker inspect demo

运行nginx会自动分配一个docker网段的ip地址

ip分配递增

  • bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。
  • 容器通过宿主机的NAT规则后可以访问外网。

 容器通过桥接到达宿主机,宿主机通过linux路由到达eth0,做伪装之后出去,所以此时容器可以访问外网

 

host

 host网络模式需要在容器创建时指定 --network=host

host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但容器的网络缺少隔离性。

宿主机如果占用端口,容器不可以再用

举例:开两个nginx,只能开启一个容器

查看日志会发现提示端口被占用

none

none模式是值禁用网络功能,只有lo接口,在容器创建时使用 --network=none指定

九、Docker 自定义网络

自定义网络模式,docker提供了三种自定义网络驱动:

  • bridge
  • overlay
  • macvlan

bridge驱动类似默认的bridge网络模式, 但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

docker1.10开始,内嵌了一个DNS server

ip是动态的,一旦重现开启容器,ip很可能会变

没用解析无法ping容器

 创建一个自定义网络

默认是172.18

比docker0递增

 自己指定一个网段

 默认不可以指定ip,创建时定义了子网的可以

 运行指定mynet1此时可以ping域名到demo2

  运行指定mynet2此时也可以ping域名到demo1

 但它们之间是隔离的,彼此是不通信的

通过使用docker network connect命令给server1添加一块网卡来使不同网桥的容器通信

 ctrl+p+q后台运行

默认接入mynet1,加网卡接入mynet2

 此时就可以ping通了

十、Docker容器通信

容器之间除了使用ip通信外,还可以使用容器名称通信。

  • docker 1.10开始,内嵌了一个DNS server。
  • dns解析功能必须在自定义网络中使用。
  • 启动容器时使用--name参数指定容器名称。

Joined容器一种较为特别的网络模式。

--network

在容器创建时使用--network=container:vm1指定(vm 1指定的是运行的容器名)

[root@server2 docker]# docker container prune 删除所有未运行的容器

[root@server2 ~]# docker pull radial/busyboxplus
[root@server2 ~]# docker tag radial/busyboxplus:latest busyboxplus:latest
[root@server2 ~]# docker rmi radial/busyboxplus:latest

处于这个模式下Docker容器会共享同一网络栈,这样两个容器之间可以使用localhost高效快速通信

--link 可以用来链接2个容器。

--link的格式:

  • --Jink <name or id>:alias
  • name和id是源容器的name和id, alias是源容器在link下的别名。

 会自动解析

容器访问外网

外网访问容器

  • 端口映射
  • -p选项指定映射端口
[root@server2 ~]# docker run -d --name demo -p 80:80 nginx
2119701a38d73b4fc9e6285e6db74679bd956450f08372627e37a99c6bb6581d
[root@server2 ~]# docker port demo
80/tcp -> 0.0.0.0:80
80/tcp -> :::80

双冗余机制,proxy和iptable只要有一个在就可以进行通信

十一、跨主机容器网络

跨主机网络解决方案

  • docker原生的overlay和macvlan
  • 第三方的flannel. weave. calico

众多网络方案是如何与docker集成在一-起的

  • libnetwork        docker容器网络库
  • CNM (Container Network Model) 这个模型对容器网络进行了抽象

macvlan网络方案实现

  • Linux kernel提供的一种网卡虚拟化技术。
  • 无需Linux bridge,直接使用物理接口,性能极好。

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

[root@server1 harbor]# cd /etc/sysconfig/network-scripts/
[root@server1 network-scripts]# cp ifcfg-eth0 ifcfg-eth1
[root@server1 network-scripts]# vim ifcfg-eth1
[root@server1 network-scripts]# ifup eth1
[root@server1 network-scripts]# ip link set eth1 promisc on

 2中同理

[root@server1 ~]# docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 macvlan1

[root@server2 ~]# docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 macvlan1


[root@server2 ~]#  docker network create -d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -o parent=eth1.1 macvlan2
[root@server1 ~]# docker network create -d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -o parent=eth1.1 macvlan2

 

 设置server2都为192.168网段,此时互通

macvlan网络间的隔离和连通

  • macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。.
  • 可以在三层上通过网关将macvlan网络连通起来。
  • docker本身不做任何限制,像传统vlan网络那样管理即可。

 [root@server2 ~]# docker network connect macvlan1 demo3

十二、Docker数据卷

docker分层文件系统

  • 性能差
  • 生命周期容器相同

docker数据卷

  • mount到主机中,绕开分层文件系统
  • 和主机磁盘性能相同,容器删除后依然保留
  • 仅限本地磁盘,不能随容器迁移

docker提供了两种卷:

  • bind mount
  • docker managed volume

bind mount

[root@server2 ~]# mkdir website
[root@server2 ~]# cd website/
[root@server2 website]# echo www.westos.org > index.html
[root@server2 website]# cd
[root@server2 ~]# docker run -d --name demo -v /root/website/:/usr/share/nginx/html nginx

此时访问一下,容器目录和本地目录同步

 bind mount默认权限是读写rw,可以在挂载时指定只读ro。

-v选项指定的路径,如果不存在,挂载时会自动创建。

 

docker managed volume

docker managed volume

  • bind mount必须指定host文件系统路径,限制了移植性。
  • docker managed volume不需要指定mount源,docker 自动为容器创建数据卷目录。
  • 默认创建的数据卷目录都在/var/lib/docker/volumes中。
  • 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中。

[root@server1 ~]# docker run -d --name demo registry

[root@server1 ~]# docker inspect demo

可以看到路径

创建

 

bind mount与docker managed volume对比

相同点:两者都是host文件系统中的某个路径。

不同点:

卷插件

docker卷默认使用的是local类型的驱动,只能存在宿主机,跨主机的volume就需要使用第三方的驱动。

docker官方只提供了卷插件的api,开发者可以根据实际需求定制卷插件驱动。

  • Docker Plugin是以Web Service的服务运行在每一台Docker Host上的,通过HTTP协议传输RPC风格的JSON数据完成通信。
  • Plugin的启动和停止,并不归Docker管理,Docker Daemon依靠在缺省路径下查找Unix Socket文件,自动发现可用的插件。
  • 当客户端与Daemon交互,使用插件创建数据卷时,Daemon会在后端找到插件对应的socket 文件,建立连接并发起相应的API请求,最终结合Daemon自身的处理完成客户端的请求。

convoy

convoy卷插件实现

  • 支持三种运行方式: devicemapper. NFS. EBS.
  • 在所有节点提前挂载NFS存储
[root@server1 ~]# tar zxf convoy-v0.5.2.tar.gz 
[root@server1 convoy]# cp convoy convoy-pdata_tools /usr/local/bin
[root@server1 convoy]# cd /usr/local/bin
[root@server1 bin]# ll
total 65024
-rwxr-xr-x 1 root root 17607008 Jan  7 15:29 convoy
-rwxr-xr-x 1 root root 23068627 Jan  7 15:29 convoy-pdata_tools
-rwx--x--x 1 root root 25907200 Jan  5 11:48 docker-compose
[root@server1 bin]# mkdir -p /etc/docker/plugins
[root@server1 bin]# echo "unix:///var/run/convoy/convoy.sock" > /etc/docker/plugins/convoy.spec
[root@server1 bin]# cat etc/docker/plugins/convoy.spec
cat: etc/docker/plugins/convoy.spec: No such file or directory
[root@server1 bin]# cat /etc/docker/plugins/convoy.spec
unix:///var/run/convoy/convoy.sock

所有节点都安装nfs-utils

[root@server1 ~]# vim /etc/exports

/mnt/nfs        *(rw,no_root_squash)

[root@server1 ~]# mkdir /mnt/nfs
[root@server1 ~]# systemctl start nfs



[root@server2 ~]# mkdir /mnt/nfs
[root@server2 ~]# mount 172.25.6.1:/mnt/nfs /mnt/nfs
[root@server1 ~]# convoy daemon --drivers vfs --driver-opts vfs.path=/mnt/nfs &
[1] 6067

[root@server1 ~]# cd /etc/docker/plugins/
[root@server1 plugins]# convoy create vol1

[root@server1 ~]# docker volume create -d convoy vol2

server2中同理

 [root@server2 plugins]# docker run -it --rm -v vol1:/data2 busybox

如果删除plugins,重启会非常慢,此时可以删除var/lib/docker/volumes/metadata.db

十三、Docker安全

Docker安全简介

Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面:

  • Linux内核的命名空间机制提供的容器隔离安全。
  • Linux控制组机制对容器资源的控制能力安全。
  • Linux内核的能力机制所带来的操作权限安全。
  • Docker程序 (特别是服务端)本身的抗攻击性。
  • 其他安全增强机制对容器安全性的影响。

控制组资源控制的安全

  • 当docker run启动一个容器时Docker将在后台为容器创建一个独立的控制组策略集合。
  • Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。
  • 确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少。

Docker服务端防护

  • 使用Docker容器的核心是Docker服务端, 确保只有可信的用户才能访问到Docker服务。
  • 将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。
  • 允许Docker服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程只允许在特定范围内进行操作。

其他安全特性

  • 在内核中启用GRSEC和PAX,这将增加更多的编译和运行时的安全检查;并且通过地址随机化机制来避免恶意探测等。启用该特性不需要Docker进行任何配置。
  • 使用一些有增强安全特性的容器模板。
  • 用户可以自定义更加严格的访问控制机制来定制安全策略。
  • 在文件系统挂载到容器内部时,可以通过配置只读模式来避免容器内的应用通过文件系统破坏外部环境,特别是一些系统运行状态相关的目录。

容器资源控制

在/sys/fs/cgroup 下面有很多诸如cpuset、cpu、 memory这样的子目录,也叫子系统。

在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),

控制组下面的资源文件里填上什么值,就靠用户执行docker run时的参数指定。

CPU限额

  • docker run -it --cpu-period= 100000 --cpu-quota=20000 ubuntu
  • cpu_ period和cpu_ quota这两个参效需要组合使用,用来限制进程在长度为cpu_ period 的一段时间内,只能被分配到总量为cpu_ quota 的CPU时间,以上设置表示20%的cpu时间。

Block IO限制

docker run -it --device-write-bps /dev/sda :30MB ubuntu

--device-write- bps限制写设备的bps

目前的block IO限制只对direct IO有效。(不使用文件缓存)

十四、Docker安全加固

LXCFS

利用LXCFS增强docker容器隔离性和资源可见性

我们直接限制内存时,查看是直接查看到宿主机的内存,看不到限制结果,所以需要增强容器隔离性,然后挂载到容器内查看。

[root@server1 ~]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm -y
[root@server1 ~]# lxcfs /var/lib/lxcfs &
[root@server1 proc]# pwd
/var/lib/lxcfs/proc
[root@server1 proc]# ls
cpuinfo  diskstats  meminfo  stat  swaps  uptime

[root@server1 proc]# docker run -it --rm -m 200M -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
root@5dc1c39f5135:/# free -m

设置特权级运行的容器: --privileged=true

有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等,相当于给了root权限

默认是普通用户权限,没有权限管理网络、磁盘等

 我们开启权限

[root@server1 proc]# docker run -it --rm  --privileged=true busybox

设置容器白名单: --cap-add

--privileged=true的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限。

例:只添加网络管理的权限

[root@server1 proc]# docker run -it --rm --cap-add=NET_ADMIN busybox

安全加固的思路

保证镜像的安全

  • 使用安全的基础镜像
  • 删除镜像中的setuid和setgid权限
  • 启用Docker的内容信任
  • 最小安装原则
  • 对镜像进行安全漏洞扫描,镜像安全扫描器: Clair
  • 容器使用非root用户运行

保证容器的安全

  • 对docker宿主机进行安全加固
  • 限制容器之间的网络流量
  • 配置Docker守护程序的TLS身份验证
  • 启用用户命名空间支持(userns-remap)
  • 限制容器的内存使用量
  • 适当设置容器CPU优先级

Docker安全的顶尖开源工具

  • Docker Bench for Security        对照安全基准审计Docker容器的脚本
  • Clair        API驱动的静态容器安全分析工具,拥有庞大的CVE数据库
  • Cilium        内核层可感知API的网络和安全工具
  • Anchore        使用CVE数据和用户定义的策略检查容器安全的工具
  • OpenSCAP Workbench        用于为各种平台创建和维护安全策略的环境
  • Dagda         用于在Docker容器中扫描漏洞、特洛伊木马、病毒和恶意软件的工具
  • Notary         使用服务器加强容器安全的框架,用于以加密方式委派责任
  • Sysdig Falco        提供了行为活动监控,可深入了解容器

十五、Docker Machine

  • Docker Machine是Docker官方编排项目之一,负责在多种平台上快速安装Docker 环境。
  • Docker Machine支持在常規Linux操作系统、虚拟化平台、openstack、公有云等不同环境下安装配置docker host。
  • Docker Machine项目基于Go语言实现

安装

[root@server1 ~]# mv docker-machine-Linux-x86_64-0.16.2 /usr/local/bin/docker-machine
[root@server1 ~]# chmod +x /usr/local/bin/docker-machine

创建machine:

创建machine要求免密登陆远程主机:

[root@server1 ~]# ssh-keygen
[root@server1 ~]# ssh-copy-id server2
[root@server1 ~]# ssh-copy-id server3

创建主机:

[root@server1 ~]# docker-machine create --driver generic --generic-ip-address=172.25.6.2 server2

 server2开启2376端口

 登陆到server2


[root@server1 ~]# docker-machine env server2  
[root@server1 ~]# eval $(docker-machine env server2)

登陆之后没有符号显示,安装bash脚本

[root@server1 ~]# mv *.bash /etc/bash_completion.d/
docker-machine.bash docker-machine-prompt.bash docker-machine-wrapper.bash 
[root@server1 ~]# vim .bashrc

PS1='[\u@\h \W$(__docker_machine_ps1)]\$ '


[root@server1 ~]# logout
Connection to 172.25.6.1 closed.
[westos@foundation37 Desktop]$ ssh -l root 172.25.6.1
root@172.25.6.1's password: 
Last login: Mon Jan 10 09:43:39 2022 from foundation37.ilt.example.com
[root@server1 ~]#  eval $(docker-machine env server2)

 

此时重新登陆有提示符了

 给没有安装docker的主机server3中创建


[root@foundation37 html]# curl https://get.docker.com/ -o get-docker.sh
[root@foundation37 html]# vim get-docker.sh 
[root@foundation37 html]# vim docker-ce.repo

[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable
enabled=1
gpgcheck=0

[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/7/extras/$basearch/
gpgcheck=0
[root@server1 ~]# docker-machine create --driver generic --generic-ip-address=172.25.6.3 --engine-install-url "http://172.25.6.250/get-docker.sh" server3

十六、Docker Compose

Docker Compose简介

  • 微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
  • Docker Compose是一种编排服务,基于pyhton语言实现,是一个用于在Docker上定义并运行复杂应用的工具,可以让用户在集群中部署分布式应用。
  • 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。
  • 解决了容器与容器之间如何管理编排的问题。

Docker Compose中两个重要概念:

  • 服务(service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。

Docker Compose实践

Compose file version 3 reference | Docker Documentation

docker-compose.yml属性

  • Image: 指定为镜像名称或镜像ID,如果镜像在本地不存在,Compose将会尝试拉取这个镜像。
  • Build:指定Dockerfile所在文件夹的路径。Compose将会利用它自动构建这个镜像,然后使用这个镜像。
  • Command:覆盖容器启动后默认执行的命令。
  • Links:链接到其它服务中的容器。
  • Ports: 端口映射。
  • Expose:暴露端口信息
  • Volumes:卷挂载路径设置
[root@server1 ~]# docker pull haproxy
[root@server1 ~]# mkdir compose
[root@server1 ~]# cd compose/
[root@server1 compose]# vim docker-compose.yml

version: "3.9"
services:
  web1:
    image: nginx
    networks:
      - mynet
    volumes:
      - ./web1:/usr/share/nginx/html

  web2:
    image: nginx
    networks:
      - mynet
    volumes:
      - ./web2:/usr/share/nginx/html

  haproxy:
    image: haproxy
    networks:
      - mynet
    volumes:
      - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    ports:
      - "80:5000"

networks:
  mynet:
[root@server1 compose]# docker network prune
[root@server1 compose]# mkdir web1
[root@server1 compose]# echo web1 > web1/index.html
[root@server1 compose]# mkdir web2
[root@server1 compose]# echo web2 > web2/index.html
[root@server1 compose]# mkdir haproxy
[root@server1 compose]# cd haproxy/
[root@server1 haproxy]# vim haproxy.cfg
#
# This is a sample configuration. It illustrates how to separate static objects
# traffic from dynamic traffic, and how to dynamically regulate the server load.
#
# It listens on 192.168.1.10:80, and directs all requests for Host 'img' or
# URIs starting with /img or /css to a dedicated group of servers. URIs
# starting with /admin/stats deliver the stats page.
#

global
        maxconn         65535
        #stats socket    /var/run/haproxy.stat mode 600 level admin
        log             127.0.0.1 local0
        #uid             200
        #gid             200
        #chroot          /var/empty
        daemon

defaults
        mode            http
        log             global
        option          httplog
        option          dontlognull
        monitor-uri     /monitoruri
        maxconn         8000
        timeout client  30s
        retries         2
        option redispatch
        timeout connect 5s
        timeout server  5s
        stats uri       /admin/stats



# The public 'www' address in the DMZ
frontend public
        bind            *:5000 name clear
        #bind            192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem

        #use_backend     static if { hdr_beg(host) -i img }
        #use_backend     static if { path_beg /img /css   }
        default_backend dynamic

# The static backend backend for 'Host: img', /img and /css.
backend dynamic
        balance         roundrobin
        server          a web1:80 check inter 1000
        server          b web2:80 check inter 1000

[root@server1 compose]# docker-compose start
[root@server1 compose]# docker-compose ps
[root@foundation37 html]# curl 172.25.6.1
web2
[root@foundation37 html]# curl 172.25.6.1
web1

 使用curl命令可以看出负载均衡

十七、Docker Swarm

  • Swarm在Docker 1.12 版本之前属于一个独立的项目,在Docker1.12版本发布之后,该项目合并到了Docker中,成为Docker的一个子命令。
  • Swarm是Docker社区提供的唯一一个原生支持Docker集群管理的工具。
  • Swarm可以把多个Docker主机组成的系统转换为单一的虚拟Docker主机,使得容器可以组成跨主机的子网网络。
  • Docker Swarm是一个为IT运维团队提供集群和调度能力的编排工具。

docker swarm相关概念

  • 节点分为管理(manager)节点和工作(worker)节点
  • 任务(Task) 是Swarm中的最小的调度单位,目前来说就是一个单一的容器。
  • 服务(Services) 是指一组任务的集合,服务定义了任务的属性。
[root@server1 ~]# docker swarm init
[root@server2 sysctl.d]# scp docker.conf server3:/etc/sysctl.d
[root@server3 yum.repos.d]# sysctl --system
[root@server2 ~]# docker swarm join --token SWMTKN-1-265u9jlnmt808kyx1oorl96r552faf79ypeswmgwzfc3kacqrb-8ykijt2t5tvzci7pl4vniguor 172.25.6.1:2377
This node joined a swarm as a worker.
[root@server3 ~]# docker swarm join --token SWMTKN-1-265u9jlnmt808kyx1oorl96r552faf79ypeswmgwzfc3kacqrb-8ykijt2t5tvzci7pl4vniguor 172.25.6.1:2377
This node joined a swarm as a worker.

将server1设置为私有仓库

[root@server1 ~]# docker node promote server2
Node server2 promoted to a manager in the swarm.
[root@server1 ~]# docker node demote server1
[root@server1 ~]# docker swarm leave
[root@server2 ~]# docker node rm server1

[root@server1 harbor]# docker-compose up -d
[root@server2 docker]# scp -r certs.d/ server3:/etc/docker/
[root@server2 docker]# scp daemon.json server3:/etc/docker/
[root@server3 docker]# systemctl daemon-reload 
[root@server3 docker]# systemctl reload docker
[root@server3 docker]# docker pull nginx

增加新节点

[root@server4 ~]# yum install -y docker-ce
[root@server4 ~]# systemctl start docker
[root@server4 ~]# vim /etc/hosts
172.25.6.1      server1 reg.westos.org

[root@server3 yum.repos.d]# scp docker-ce.repo  server4:/etc/yum.repos.d/
[root@server3 yum.repos.d]# cd /etc/sysctl.d/
[root@server3 sysctl.d]# scp docker.conf server4:/etc/sysctl.d/
[root@server3 docker]# scp -r certs.d/ daemon.json server4:/etc/docker/


[root@server2 ~]# docker service create --name webcluster -p 80:80 --replicas 3 nginx
[root@server4 ~]# docker swarm join --token SWMTKN-1-265u9jlnmt808kyx1oorl96r552faf79ypeswmgwzfc3kacqrb-8ykijt2t5tvzci7pl4vniguor 172.25.6.2:2377
[root@server2 ~]# docker service ps webcluster 

部署swarm监控

https://github.com/dockersamples/docker-swarm-visualizer

[root@server1 harbor]# docker pull dockersamples/visualizer:stable

[root@server1 harbor]# docker tag dockersamples/visualizer:stable reg.westos.org/library/visualizer:latest
[root@server1 harbor]# docker push reg.westos.org/library/visualizer:latest

[root@server2 ~]# docker service create \
>   --name=viz \
>   --publish=8080:8080/tcp \
>   --constraint=node.role==manager \
>   --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
>   visualizer

访问http://172.25.6.2:8080/

 关闭sercer3的服务

[root@server3 docker]# systemctl stop docker.service

可以看到高可用副本转移到server4中

 滚动更新

[root@server2 ~]# docker service rm webcluster 

[root@server1 harbor]# docker pull ikubernetes/myapp:v1
[root@server1 harbor]# docker pull ikubernetes/myapp:v2
[root@server1 harbor]# docker tag ikubernetes/myapp:v1 reg.westos.org/library/myapp:v1
[root@server1 harbor]# docker tag ikubernetes/myapp:v2 reg.westos.org/library/myapp:v2
[root@server1 harbor]# docker push  reg.westos.org/library/myapp:v1
[root@server1 harbor]# docker push  reg.westos.org/library/myapp:v2
[root@server2 ~]# docker service create --name webcluster -p 80:80 --replicas 3 myapp:v1
[root@server2 ~]# docker service scale webcluster=10

[root@server2 ~]# docker service update --image myapp:v2 --update-parallelism 2 --update-delay 5s webcluster 

 用脚本更新

[root@server2 ~]# docker service rm webcluster 

version: "3.9"
services:

  webcluster:
    image: myapp:v1
    ports:
      - "80:80"
    deploy:
      replicas: 3
      update_config:
        parallelism: 2
        delay: 5s
      restart_policy:
        condition: on-failure
~                                                 
[root@server2 ~]# docker stack deploy web -c webcluster.yml 

改成版本2

 

 node.role == manager指定这个service的实例均运行在swarm manager节点上,不会分到worker节点

  visualizer:
    image: visualizer
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints:
          - "node.role==manager"
[root@server2 ~]# vim webcluster.yml 
[root@server2 ~]# docker stack deploy web -c webcluster.yml 
Updating service web_webcluster (id: jn9m5q6ob3p8kcrkds7mvrcpi)
Creating service web_visualizer
[root@server2 ~]# docker stack ls
NAME      SERVICES   ORCHESTRATOR
web       2          Swarm
[root@server2 ~]# docker stack ps web

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值