一、docker简介

Docker是管理容器的引擎。
Docker为应用打包、部署平台,而非单纯的虚拟化技术

1.VM vs Container

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作

2.传统虚拟机和容器的技术对比

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_02

3.容器是如何工作的

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_03

二、容器配置

1.搭建docker仓库

[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0

由于下载过程中会出现很多的依赖性,这些依赖性都是从centos源里面找到的,所以这里我们还需搭建一个centos源,这里可以参考阿里云镜像站

[root@server1 yum.repos.d]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
[root@server1 yum.repos.d]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
[root@server1 yum.repos.d]# vim CentOS-Base.repo
:%s/$releasever/7/g                      ## 因为我用的是redhat操作系统,所以需要修改一下路径,替换成7就可以了

修改后的CentOS-Base.repo如下:

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#
 
[base]
name=CentOS-7 - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#released updates 
[updates]
name=CentOS-7 - Updates - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that may be useful
[extras]
name=CentOS-7 - Extras - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/extras/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-7 - Plus - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#contrib - packages by Centos Users
[contrib]
name=CentOS-7 - Contrib - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

列一下仓库,如果没有问题直接下载即可

2.下载docker-ce

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

3.开启服务,并开机自启

[root@server1 yum.repos.d]# systemctl start docker
[root@server1 yum.repos.d]# systemctl enable docker

4.查看docker 信息

[root@server1 yum.repos.d]# docker info

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_04


如果查看info中出现以下报错

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_05


解决方法如下:

[root@server1 sysctl.d]# pwd
/etc/sysctl.d
[root@server1 sysctl.d]# vim  docker.conf 
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
[root@server1 sysctl.d]# sysctl  --system               ##生效
ip addr 查看多了一个docker0

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_06

5.测试

[root@server1 ~]# docker search yakexi007
NAME                 DESCRIPTION   STARS     OFFICIAL   AUTOMATED
yakexi007/game2048                 0                    
yakexi007/mario                    0                    
yakexi007/nginx                    0   
[root@server1 ~]# docker pull yakexi007/game2048       ## 拉取镜像

本地加载[root@server1 ~]# docker load -i mario.tar

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_07

[root@server1 ~]# docker history yakexi007/game2048:latest

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_08


做端口映射 第一个80是宿主机的,第二个对应镜像的端口

-d是打入后台,–name 是给镜像取个名字

[root@server1 ~]# docker run -d --name game2048 -p 80:80 yakexi007/game2048
[root@server1 ~]# docker ps                         ##查询端口连接情况 
[root@server1 ~]# docker ps -a               ## 查看所有的,包括已经停掉的

然后访问docker主机的ip即可

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_09


这里是mario的,和2048操作相同

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_10


删除已经拉取的镜像

[root@server1 ~]# docker rm -f game2048

三、docker镜像

1.镜像的分层结构

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_11


共享宿主机的kernel

base镜像提供的是最小的Linux发行版

同一docker主机支持运行多种Linux发行版

采用分层结构的最大好处是:共享资源

拉取一个busybox作为实验环境

[root@server1 ~]# docker pull busybox
[root@server1 ~]# docker history busybox:latest

会执行shell ,提供一个环境,交互式

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_12


进入交互式

[root@server1 ~]# docker run -it busybox

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_13


会提供一个ip ,在容器的ip上递增,内核版本信息和宿主机一模一样

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_14


当我们CLRT+d 推出那个交互式环境之后,我们再次查看进程,发现已经没有进程了,

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS                     PORTS     NAMES
e978bf7bc71f   busybox   "sh"      10 minutes ago   Exited (0) 7 minutes ago             practical_cohen
[root@server1 ~]# docker start e978bf7bc71f
e978bf7bc71f
[root@server1 ~]# docker container attach e978bf7bc71f                  ## 使用这个命令可以直接进入

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_15


注意 CTRL+p+q 是打入后台,可以退出交互式环境,也还可以保留进程Copy-on-Write 可写容器层,容器层以下所有镜像层都是只读的,docker从上往下依次查找文件,容器层保存镜像变化的部分,并不会对镜像本身进行任何修改,一个镜像最多127层。

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_16


实验验证:

[root@server1 ~]# docker container attach e978bf7bc71f      ## 附加到容器id上
/ # touch file1
/ # touch file2
/ # touch file3
[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS                     PORTS     NAMES
e978bf7bc71f   busybox   "sh"      36 minutes ago   Exited (0) 8 seconds ago             practical_cohen
[root@server1 ~]# docker rm e978bf7bc71f
e978bf7bc71f
[root@server1 ~]# docker run -it --rm busybox                                     ##加--rm 是自动回收 
/ # ls

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_17

2.镜像的构建

  • docker commit 构建新镜像三部曲
  • 运行容器
  • 修改容器
  • 将容器保存为新的镜像
  • 缺点:
  • 效率低、可重复性弱、容易出错
  • 使用者无法对镜像进行审计,存在安全隐患
    (一)运行容器
[root@server1 ~]# docker run -it  --name demo busybox

(二)将容器保存为新的镜像

[root@server1 ~]# docker commit -m "add files" demo demo:v1

(三)查看镜像

[root@server1 ~]# docker images

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_18


相当于在原来的busybox基础上加了一层.

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_19


当我们回收掉容器demo后,再次运行一下demo:v1查看数据

[root@server1 ~]# docker rm demo
[root@server1 ~]# docker run -it --name demo demo:v1
/ # ls

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_20


创建一个Dockerfile

[root@server1 ~]# docker rm demo
[root@server1 ~]# docker rmi demo:v1 
[root@server1 ~]# mkdir docker
[root@server1 docker]# vim Dockerfile
FROM busybox
RUN touch file1
RUN mkdir westos

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_21


构建镜像

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

从当前目录中找Dokerfile ,运行里面的指令

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_22

[root@server1 docker]# docker images
[root@server1 docker]# docker history  demo:v1

在history里我们可以详细的看到所运行的所有指令。一目了然。

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_23


Dokerfile 最佳实践

每一步操作都是由docker commit来实现的,每一条指令生成一个镜像层

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_24

[root@server1 docker]# vim Dockerfile
FROM demo:v1
RUN touch file2
RUN mkdir redhat
[root@server1 docker]# docker build -t demo:v2 .
[root@server1 docker]# docker images
[root@server1 docker]# docker history  demo:v2

在demo:v1的基础上又加了两层

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_25

四、Dockerfile详解

还原环境

[root@server1 docker]# docker rmi demo:v1
[root@server1 docker]# docker rmi demo:v2

1.dockerfile常用指令

(1) FROM

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

(2) MAINTAINER

设置镜像的作者,比如用户邮箱等。

(3) COPY

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

示例:

[root@server1 docker]# vim index.html
www.sun.com
[root@server1 docker]# vim Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_26


查看

[root@server1 docker]# docker images
[root@server1 docker]# docker history  demo:v1

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_27


进入交互式页面,查看刚才指令是否执行成功

[root@server1 docker]# docker run -it --rm demo:v1

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_28

(4)ADD

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

[root@server1 docker]# tar zcf test.tar.gz /etc
[root@server1 docker]# vim Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
[root@server1 docker]# docker build -t demo:v2 .

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_29


查看效果:

[root@server1 docker]# docker images
[root@server1 docker]# docker history  demo:v2
[root@server1 docker]# docker run -it --rm demo:v2

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_30

(4) ENV

设置环境变量,变量可以被后续的指令使用:
ENV HOSTNAME sevrer1
示例:

[root@server1 docker]# vim Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
ENV HOSTNAME server1
[root@server1 docker]# docker build -t demo:v3 .

查看命令和之前相同,这里直接验证最后结果

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_31

(5) EXPOSE

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

[root@server1 docker]# vim Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
ENV HOSTNAME server1
EXPOSE 80

[root@server1 ~]# docker run -d --name demo -P nginx
[root@server1 ~]# docker inspect demo

随机指定端口:

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_32

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_33


将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_34

(6) VOLUME

申明数据卷,通常指定的是应用的数据挂在点:
VOLUME ["/var/www/html"]

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# docker build -t demo:v4 .
[root@server1 docker]# docker images
[root@server1 docker]# docker history  demo:v4
[root@server1 docker]# docker run -it --name demo demo:v4
/ # cd /data/
/data # ls
/data # touch dokerfile1
这里不要直接退出,将其打入后台 CTRL+P+Q,保证进程 一直存在

查看/data是否成功挂载

[root@server1 docker]# docker inspect demo

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_35


上图我们看到/data实际上挂载到了我选中的那个路径中,数据也存在在宿主机里面,然后我们测试删掉文件,然后重新见一个文件,再次进入demo中查看,我们新建的文件也存在。说明容器可以做数据持久化。

[root@server1 docker]# cd /var/lib/docker/volumes/ad7567a0c7d9a0694ea1f3ea1798bd12a8b1f3eb036a8cd3476359c6c7e6db19/_data
[root@server1 _data]# ls
dokerfile1
[root@server1 _data]# rm -f dokerfile1 
[root@server1 _data]# cp /etc/passwd .
passwd
[root@server1 _data]# docker attach demo 
/data # ls
passwd

用以下命令我们可以将没有被挂载的数据

[root@server1 _data]# docker rm demo 
demo
[root@server1 _data]# docker volume ls
DRIVER    VOLUME NAME
local     ad7567a0c7d9a0694ea1f3ea1798bd12a8b1f3eb036a8cd3476359c6c7e6db19
[root@server1 _data]# docker volume  prune

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_运维_36

(7) WORKDIR

为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。

(8) RUN

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

(9) CMD 与 ENTRYPOINT

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

[root@server1 docker]# cat Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
CMD echo "hello world"
[root@server1 docker]# docker build -t demo:v5 .
[root@server1 docker]# docker  run --rm demo:v5

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_37

[root@server1 docker]# cat Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
CMD ["/bin/sh", "-c", "echo hello $HOSTNAME"]                         ## 解析变量
[root@server1 docker]# docker build -t demo:v9 .
[root@server1 docker]# docker  run --rm demo:v9

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_38

[root@server1 docker]# cat Dockerfile 
FROM busybox
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt 
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
ENTRYPOINT ["echo hello"]
CMD ["world"]
[root@server1 docker]# docker build -t demo:v10 .
[root@server1 docker]# docker  run --rm demo:v10
[root@server1 docker]# docker  run --rm demo:v10 linux

我们可以看的CMD后的东西是可以被覆盖的

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_CentOS_39

五、配置镜像加速器

容器镜像服务

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_40


将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_41


在阿里云注册,每个人都可以有免费加速

[root@server1 docker]# cd   /etc/docker/
[root@server1 docker]# vim daemon.json
{
  "registry-mirrors": ["https://2r0ei25n.mirror.aliyuncs.com"]
}
[root@server1 docker]# systemctl daemon-reload 
[root@server1 docker]# systemctl reload docker.service

六、镜像的优化

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

1.实例分析:

这里我们使用nginx镜像制作作为示例
首先我们需要搭建base,这里使用的是rhel7,
链接:rhel7 提取码: k2dm

[root@server1 test]# docker load -i rhel7.tar
  • 编写Dockerfile 文件
[root@server1 ~]# mkdir test
[root@server1 ~]# cd test/
[root@server1 test]# vim Dockerfile
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make &&  yum clean all

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

这里我们还需要nginx-1.18.0的tar包放在test目录下

链接:nginx tar包 提取码: tscn

还需要将本地的yum源放置test目录下

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_42

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

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_docker_43


这里我们看到我们构建出来的nginx镜像144M,由于我们知道官方的nginx镜像是133M,所以需要做优化。

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_44


我们可以看到刚才的base rhel7就占140M,我们要再优化的话只能从base入手,所以我们需要换一个小一点的base

下面我们就使用goole最简base做实验,对比刚才做好的镜像大小。

七、构建nginx容器镜像

首先我们使用goolge的最简base
链接: base-debian10.tar提取码: n8xf

1.创建base环境

[root@server1 ~]# docker load -i base-debian10.tar
[root@server1 nginx]# docker pull nginx
[root@server1 ~]# mkdir nginx

2.编写Dockefile

[root@server1 nginx]# vim Dockerfile
FROM nginx:1.19.2 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 Dockefilehttps://github.com/kyos0109/nginx-distroless/blob/master/Dockerfile

3.执行built

[root@server1 nginx]# docker build -t webserver:v1 .
[root@server1 nginx]# docker images

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_45


我们可以封装完看到只有31.6MB,比官方的要小的多

4.运行测试

[root@server1 nginx]# docker run -d --name webserver webserver:v1
[root@server1 nginx]# docker ps
[root@server1 nginx]# docker inspect  webserver

将其打入后台,查看端口,进行访问

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_46


我们可以看到已经成功访问到了nginx的默认发布页面,到这里就说明我们已经成功构建nginx镜像了。

将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_镜像制作_47


将服务器上docker镜像下到本地并修改 docker镜像服务器搭建_linux_48


从上图我们通过对比两次制作的nginx镜像大小,我们看到通过优化之后的镜像大小只有31.6M,比官方的要小的多。