Docker容器入门篇

第1章 Docker简介

1.1 Docker容器介绍

Docker官网:https://www.docker.com/

什么是docker?

Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)

Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目已经超过 4 万 6 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroupnamespace,以及AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 开始,则进一步演进为使用 runC 和 containerd

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。

下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

                                                                          传统虚拟化

                                                                           Docker 

1.2 对Docker容器通俗解释

如果需要通俗的描述容器的话,我觉得容器就是一个存放东西的地方,就像书包可以装各种文具、衣柜可以放各种衣服、鞋架可以放各种鞋子一样。我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境。

1.3 图解物理机、虚拟机与容器

物理机:

虚拟机:

容器:

通过上面这三张抽象图,我们大概可以通过类比概括出: 容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些

1.4 Docker的理念

容器的核心理念在于通过镜像将运行环境打包,实现“一次构建,处处运行”,从而避免了运行环境不一致导致的各种异常

Build(构建镜像):镜像就像是集装箱包括文件以及运行环境等等资源

Ship(运输镜像):主机和仓库间运输,这里的仓库就像是超级码头一样。

Run (运行镜像):运行的镜像就是一个容器,容器就是运行程序的地方

1.5 Docker组成

1.5.1 镜像

我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu 16.04 最小系统的 root 文件系统。Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变

分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像

1.5.2 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, 使用数据卷后,容器可以随意删除、重新run,数据却不会丢失

1.5.3仓库

镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。

一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。所以说:镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

镜像仓库实现方式按使用范围可以分为Docker Hub 和 Docker Registry两类,前者是在公网环境下面向所有容器使用者开放的镜像服务,后者是供开发者或公司在内部环境下搭建镜像仓库服务,由于公网下载镜像的网络带宽、延迟限制以及可控性的角度考虑,在私有云环境下通常需要采用 Docker Registry 来搭建自己的镜像仓库服务。

最常使用的Registry公开服务是官方的Docker Hub ,这也是默认的Registry,并拥有大量的高质量的官方镜像,网址为:hub.docker.com

1.6 为什么要用Docker

  • Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“这段代码在我机器上没问题啊”这类问题;——一致的运行环境
  • 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间
  • 避免公用的服务器,资源会容易受到其他用户的影响。——隔离性
  • 善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展
  • 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便
  • 使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署

面向产品:产品交付

面向开发:简化环境配置

面向测试:多版本测试

面向运维:环境一致性

面向架构:自动化扩容(微服务)

1.7 容器 VS 虚拟机

简单来说: 容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。

两者对比图

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

1.7.1容器与虚拟机 (VM) 总结

容器是一个应用层抽象,用于将代码和依赖资源打包在一起。 多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动 。

虚拟机(VM)是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个VM在一台机器上运行。每个VM都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且VM启动也十分缓慢 。

第2章 Docker 安装及管理

2.1 系统环境

[root@www ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@www ~]# uname -r
3.10.0-862.9.1.el7.x86_64
[root@www ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)
[root@www ~]# getenforce
Disabled

2.2 安装docker

2.2.1下载yum源

清华镜像站地址: https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/

$ cd /etc/yum.repos.d/
$ wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo    #下docker源

2.2.2 安装docker

$ yum -y install docker-ce   #安装docker
$ systemctl start docker     #启动docker
$ systemctl status docker    #检查状态
$ docker -version            #查看docker版本
$ docker info                #查看docker详情
$ systemctl enable docker-ce #设置开机自启动
$ docker search centos       #搜索centos镜像

2.2.3 Docker下载第一个镜像

$ docker pull centos    #默认下载最新版镜像
$ docker pull centos:7.2.1511  #可以指定版本下载镜像
$ docker images #查看本地存储的镜像
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              7.2.1511            ddc0fb7d7a72        5 weeks ago         195MB
centos              latest              5182e96772bf        5 weeks ago         200MB

2.2.4 Docker commit 命令

语法

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS说明:

•     -a :提交的镜像作者;

•     -c :使用Dockerfile指令来创建镜像;

•     -m :提交时的说明文字;

•     -p :在commit时,将容器暂停。

实例

$ docker commit -a "runoob.com" -m "my apache" a404c6c174a2  mymysql:v1
$ docker images mymysql:v1
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mymysql             v1                  37af1236adef        15 seconds ago      329 MB

2.2.5 Docker镜像导入导出

$ docker save -o centos.tar centos         #在当前目录生成一个docker镜像文件
$ docker save centos >/tmp/centos.tar      #指定目录生成docker镜像文件
$ docker load --input centos.tar           #当前目录导入镜像
$ docker load  </tmp/centos.tar            #指定目录镜像导入

2.2.6 Docker镜像删除

$ docker rmi 镜像名或者ID
列如:docker rmi centos

2.2.7 启动容器

启动镜像有两种方式,在本地有镜像的基础上启动或者在本地没有镜像的基础上启动会直接从https://hub.docker.com/explore/ 下载镜像

测试hello world

$ docker run centos /bin/echo "Hello world"  #centos为镜像名称,启动镜像并执行echo之后退出
$ docker ps -a #查看所有容器包括已经退出的
CONTAINER ID   IMAGE        COMMAND            CREATED     STATUS    PORTS               NAMES
db44b009f5a5  centos  "/bin/echo 'Hello wo…" 2 minutes ago Exited (0) 2 minutes ago                    objective_benz

CONTAINER ID: 容器Id IMAGE:镜像名称 COMMAND:执行的命令 CREATED:创建的时间 STATUS:状态(Exited为退出|up为启动) NAMES:镜像名称,不手动指定,docker会随机生成 $ docker ps #只查看正在运行的docker容器 #注意docker只会在前台运行一个任务,如果任务结束docker容器就停止了

启动容器并进入:

$ docker run -name mydocker -t -i centos /bin/bash
[root@ef0d82a174e8 /]#                   #表示已经进入容器
#docker run 固定语法
#-name :容器名称
# -t   :打开一个tty终
# -i   :打开标准输入
# centos:镜像名
# /bin/bash:执行的命令
#注意此方法exit退出容器,容器就会停止可以ps -a查看
$ systemctl start 容器ID或者名称        #启动已经停止的容器

容器启动完之后3中方式进入容器

方法一
$ docker attach mydocker   #不推荐
方法二 $ yum install -y util-linux #如果本机没有nsenter命令则执行安装,有的话请忽略 $ docker inspect --format "{{.State.Pid}}" mydocker #获取容器第一个进程的PID $ nsenter --target 28457 --mount --uts --ipc –net -pid #进入容器 [root@ef0d82a174e8 /]# 进入docker容器脚本 $ vim docker_in.sh #!/bin/bash docker_in(){ NAME_ID=$1 PID=$(docker inspect --format "{{.State.Pid}}" $NAME_ID) nsenter --target $PID --mount --uts --ipc --net --pid } docker_in $1 $ chmod +x docker_in.sh #加入执行权限 ./docker_in.sh mydocker #后面加入容器名称直接进入容器,exit退出不会关闭容器 [root@ef0d82a174e8 /]# 方法三 $ docker exec -it mydocker /bin/bash #exit退出容器不会关闭

2.2.8 小结

搜索镜像:docker search
获取镜像:docker pull
查看镜像:docker images
删除镜像:docker rmi
启动容器:docker run -name -h hostname
docker run -name mydocker -i -t centos /bin/bash
停止容器:docker stop 容器名称或者ID
查看容器:docker ps -a -l
进入容器:docker exec | docker attach |nsenter
删除容器:docker rm
打包镜像:docker commit

第3章 Docker网络访问和数据管理

3.1 端口映射

3.1.1 随机端口映射

$ docker pull nginx                 #pull一个nginx来设置怎么可以访问到nginx
$ docker run -d -P nginx
-d :后台运行
-P :随机端口映射
$ docker ps -a #可以查看到容器将本机的32647映射成了容器nginx 的80端口
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                   NAMES
9f17e303b265        nginx               "nginx -g 'daemon of…"   53 seconds ago      Up 53 seconds             0.0.0.0:32768->80/tcp   hardcore_kilby

浏览器访问本机:IP地址:32678

3.1.2 指定端口映射

$ docker run -d -p 3333:80 --name nginx-demo nginx       #本机3333映射到80端口-name为容器起个名如果有多个端口,加多个-p就可以了

3.2 Docker数据存储

3.2.1 随机挂载

$ docker run -d --rm --name nginx-test1 -v /data nginx  #将本机的一个目录挂载到容器的/data
查看本机挂载的目录
$ docker inspect nginx-test1   #找到如下source下的目录就是本机目录
        "Mounts": [
            {
                "Type": "volume",
                "Name": "ddf57cbce723cc0b011f1807d2b7b6de7383b810fdf404498a0f7dd5814abcdc",
                "Source": "/var/lib/docker/volumes/ddf57cbce723cc0b011f1807d2b7b6de7383b810fdf404498a0f7dd5814abcdc/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""

3.2.2 指定挂载

$ mkdir -p /data/docker-volume-nginx    #本机创建一个测试目录
$ docker run -d --name nginx-test2 -v /data/docker-volume-nginx/:/data/ nginx

3.3 Docker数据卷

开发环境:开发代码挂载到容器

生产环境:存储持久化数据

数据卷就是单独起一个容器,然后让别的容器直接挂载这个数据卷容器

$ docker run -d --name volume-demo -v /data:/data nginx   #起一个数据卷容器
$ docker run -d --name nginx-volume-demo --volumes-from volume-demo nginx  #新起容器直接挂载通过--volumes-from参数挂载
#注意,数据卷容器挂掉之后并不会影响使用

第4章 Docker镜像主动构建

什么是手动构建:

启动一个容器,安装上我们需要的包,然后包容器变成镜像

$ docker run --name mynginx -it centos /bin/bash   #启动一个容器来安装nginx
以下为容器中操作
[root@e2582e9fe18f /]# rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm  #安装epel源
[root@e2582e9fe18f /]# yum -y install nginx   
[root@e2582e9fe18f /]# yum clean all          #清除一下缓存,减小镜像大小
[root@e2582e9fe18f /]# vi +3 /etc/nginx/nginx.conf 
daemon off;                                    #加入此项让nginx在前台运行
将nginx安装好之后,就在宿主机直接提交成镜像
$ docker commit -m "My nginx" e2582e9fe18f mynginx:v1 #-m是注释,mynginx:v1为镜像名称
$ docker run -d -p 91:80 mynginx:v1 nginx  #启动容器

浏览器访问:ip+端口 可以看到能够成功访问

手工构建方式不太方便,不推荐

第5章 Dockerfile自动构建Docker镜像

Dockerfile文件需要包括

基础镜像信息

维护者信息

镜像操作指令

容器启动时执行指令

FROM:指定基础镜像
MAINTAINER:指定维护者信息
RUN:在命令前面加上RUN即可
ADD:copy文件,会自动解压
WORKDIR:设置当前工作目录
VOLUME:设置卷,挂载主机目录
EXPOSE:指定对外的端口
CMD:指定容器启动后的要干的事情

创建dockerfile文件和目录

$ mkdir -p /opt/dockerfile/mynginx    #创建目录
$ cd /opt/dockerfile/mynginx
$ vim Dockerfile    #注意D一定要大写
#Base Image
FROM centos                  #指定镜像

#Maintainer
MAINTAINER 921390093@qq.com  #维护者信息

#Run
RUN rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm #安装epel源
RUN yum -y install nginx --enablerepo=epel    #安装nginx
RUN echo "daemone off;" >>/etc/nginx/nginx.conf   #设置前台启动
ADD index.html /usr/share/nginx/html/index.html   #设置前台启动或者直接将配置文件cp进容器,这里是测试专门的一个index.html,作用和上面这条命令一样
EXPOSE 80            #开启的端口
CMD ["nginx"]        #要执行的命令

执行docker构建

在Dockerfile所在目录执行

$ docker build -t mynginx:v2 .       #最后有一个点,-t表示打标签,点表示在当前目前查找Dockerfile文件

第6章 Docker生产镜像构建实战

6.1 创建一个系统基础镜像

在/opt/dockerfile/创建多个目录用来存放不同运行环境的镜像

需要吧Docker字符集和时区设置好,要不然会各种坑

$ cd /opt/dockerfile
$ mkdir system app runtime
$ mkidr system/centos              #system目录下可以创建别的操作系统目录,一个系统一个目录
$ tree        #树状形式显示 
.
├── app
├── mynginx
│   ├── Dockerfile
│   └── index.html
├── runtime
└── system
└── centos
$ cd system/centos
$ vim Dockerfile
#Base Image
FROM centos

#Maintainer
MAINTAINER 921390093@qq.com

ENV TZ=Asia/Shanghai

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone

#Run
RUN rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm
RUN yum -y install kde-l10n-Chinese glibc-common lrzsz dos2unix tree nmap nc dos2unix telnet nc sl telnet sl bash-completion vim net-tools wget curl lsof && yum clean all
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ENV LC_ALL zh_CN.utf8

在Dockerfile目录执行

$ docker build -t system/centos:v1 .

6.2 创建一个带ssh远程连接的镜像

$ mkdir -p /opt/dockerfile/system/centos-ssh
$ cd /opt/dockerfile/system/centos-ssh
$ vim Dockerfile
#Base Image
FROM centos

#Maintainer
MAINTAINER 921390093@qq.com

#Time zone
ENV TZ=Asia/Shanghai

#Set the time zone
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone

#Run
RUN rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm
RUN yum -y install kde-l10n-Chinese glibc-common openssh-clients openssh-server openssl-devel lrzsz dos2unix tree nmap nc dos2unix telnet nc sl telnet sl bash-completion vim net-tools wget curl lsof && yum clean all
RUN ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N ''
RUN ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ''
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_ed25519_key  -N ''

#Set root password
RUN echo "root:131400"| chpasswd

#Set character set
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ENV LC_ALL zh_CN.utf8

在Dockerfile目录执行

$ docker build -t system/centos:v2 .

测试启动容器

$ docker run -d --name centos-ssh -p 8022:22 system/centos:v2 /usr/sbin/sshd –D
[root@jhkj69 centos]# docker ps -l  #查看容器
CONTAINER ID        IMAGE               COMMAND               CREATED              STATUS              PORTS                  NAMES
679010f48414        system/centos:v2    "/usr/sbin/sshd -D"   About a minute ago   Up About a minute   0.0.0.0:8022->22/tcp   centos-ssh
[root@jhkj69 centos]# ssh 192.168.3.69 -p8022      #直接测试ssh到容器,可以看到是成功的
The authenticity of host '[192.168.3.69]:8022 ([192.168.3.69]:8022)' can't be established.
ECDSA key fingerprint is 41:fe:36:58:4c:79:cd:55:79:f8:18:db:5f:a2:af:a9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.3.69]:8022' (ECDSA) to the list of known hosts.
root@192.168.3.69's password: 
[root@679010f48414 ~]#

6.3 使用Supervisor来管理多进程

supervisor管理进程,是通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就好了。此时被管理进程被视为supervisor的子进程,若该子进程异常中断,则父进程可以准确的获取子进程异常中断的信息,通过在配置文件中设置autostart=ture,可以实现对异常中断的子进程的自动重启

6.3.1获取supervisor配置文件

$ yum -y install supervisor
$ vim /etc/supervisord.conf 
nodaemon=true    #将flase改为true,设置为前台启动
[include]
files = supervisord.d/*.ini   #这是将.ini配置文件包含进来的参数
将配置文件下载下来保存到本地,上面的操作只是需要一个supervisor的配置文件而已

详情请参考:https://www.jianshu.com/p/3658c963d28b

6.3.2 构建ssh+supervisor镜像

vim /opt/dockerfile/system/centos-ssh/Dockerfile
#Base Image
FROM centos

#Maintainer
MAINTAINER 921390093@qq.com

#Time zone
ENV TZ=Asia/Shanghai

#Set the time zone
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone

#Run
RUN rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm
RUN yum -y install kde-l10n-Chinese glibc-common supervisor openssh-clients openssh-server openssl-devel lrzsz dos2unix tree nmap nc dos2unix telnet nc sl telnet sl bash-completion vim net-tools wget curl lsof && yum clean all
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key

#Set root password
RUN echo "root:131400"| chpasswd   

#For Supervisor
ADD supervisord.conf /etc/supervisord.conf
ADD sshd.ini /etc/supervisord.d/sshd.ini

#Set character set
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ENV LC_ALL zh_CN.utf8

#Outside port
EXPOSE 22

CMD ["/usr/bin/supervisord","-c","/etc/supervisord.conf"]

将supervisord.conf上传到Dockerfile所在目录并编写sshd.ini

vim /opt/dockerfile/system/centos-ssh/sshd.ini  #如果有多个服务就写多个ini
[program:sshd]                     
command=/usr/sbin/sshd -D          #执行命令路径  
process_name=%(program_name)s      #进程名字
autostart=true                     #程序崩溃时自动重启,重启次数是有限制的,默认为3次

6.3.3 连接容器并验证

[root@www centos-ssh]# ssh 39.106.119.82 -p2222
root@39.106.119.82's password: 
Last login: Sat Sep 15 15:58:35 2018 from 39.106.119.82           #很明显有两个进程
[root@bfa084d0d05a ~]# ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  1.4 120744 14824 ?        Ss   15:58   0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisord.conf
root         8  0.0  0.4 112812  4284 ?        S    15:58   0:00 /usr/sbin/sshd -D
root        31  0.6  0.5 155232  6004 ?        Ss   16:28   0:00 sshd: root@pts/0
root        33  0.5  0.2  17448  2556 pts/0    Ss   16:28   0:00 -bash
root        52  0.0  0.1  56816  1852 pts/0    R+   16:29   0:00 ps –aux

6.4 构建JDK+Tomcat运行环境镜像

JDK下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

将下载好的jdk放入到和Dockerfile所在的目录

$ cd /opt/dockerfile/runtime/tomcat
$ ls                              #这是目录下的几个文件,必须要的
Dockerfile  jdk-8u60-linux-x64.tar.gz  tomcat.ini
$ vim Dockerfile
#Base Image
FROM system/centos
#Maintainer
MAINTAINER 921390093@qq.com
#Create Dir
RUN mkdir /server/tools -p && mkdir /application
#For Supervisor
ADD tomcat.ini /etc/supervisord.d/tomcat.ini
#pwd 
WORKDIR /server/tools
#Jdk install env
ADD jdk-8u60-linux-x64.tar.gz /application
RUN ln -s /application/jdk1.8.0_60 /application/jdk
ENV JAVA_HOME /application/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH .:$JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH $PATH:$JAVA_HOME/bin
#Tomcat env
RUN wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.34/bin/apache-tomcat-8.5.34.tar.gz
RUN tar xf apache-tomcat-8.5.34.tar.gz -C /application
RUN ln -s /application/apache-tomcat-8.5.34 /application/tomcat
#Set character set
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ENV LC_ALL zh_CN.utf8

#Outside port
EXPOSE 22 8080

CMD ["/usr/bin/supervisord","-c","/etc/supervisord.conf"]

tomcat.ini配置文件

$ vim tomcat.ini
[program:tomcat]
command=/application/tomcat/bin/catalina.sh run
process_name=%(program_name)s
autostart=true

执行构建

$ docker build -t system/centos .

启动容器并测试

$ docker run -d --name tomcat -p 3022:22 -p 8080:8080 tomcat

浏览器访问本机:192.168.3.69:8080

只需要将对应的java的开发包放入到tomcat即可

ssh 连接测试

[root@jhkj69 app]# ssh 192.168.3.69 -p 3022
The authenticity of host '[192.168.3.69]:3022 ([192.168.3.69]:3022)' can't be established.
ECDSA key fingerprint is 19:82:44:44:35:e8:05:92:d8:f3:5f:bd:a5:6f:89:a0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.3.69]:3022' (ECDSA) to the list of known hosts.
root@192.168.3.69's password: 
[root@285eb0e96580 ~]#
[root@285eb0e96580 ~]# netstat –lntup  #可以看到8080和22随容器启动而启动
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      11/java             
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      10/sshd             
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      11/java             
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      11/java             
tcp6       0      0 :::22                   :::*                    LISTEN      10/sshd  

6.5 构建Jenkins镜像

Jenkins官网下载war直接放入tomcat

https://jenkins.io/

Dockerfile所在目录进行构建

$ docker build -t tomcat/jenkins .

浏览器访问: http://192.168.3.69:92/jenkins

也可以直接将jenkins安装好之后进行commit也可以,方法多种,适合自己就行

第7章 Docker私有仓库构建

7.1 Docker官方仓库registry

Docker官方提供的仓库

$ docker run -d --name docker-registry -p 5000:5000 registry

默认情况下,docker使用的是官网仓库,如果想要使用本地仓库的话,要将docker的json加入信任

$ vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries" : ["http://192.168.3.69:5000"]
}

重启docker

$ systemctl restart docker

启动docker-registry

$ systemctl start docker-registry

将镜像打标签,可以看到写一下黄色标注

$ docker tag system/centos 192.168.3.69:5000/system/centos   
$ docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
tomcat/jenkins                    latest              c986650c9859        3 hours ago         804MB
tomcat                            latest              74cc72cd7b7b        13 hours ago        728MB
system/centos                     v3                  1296aa4446a5        13 hours ago        335MB
192.168.3.69:5000/system/centos   latest              9870e61e811b        14 hours ago        331MB
system/centos                     v2                  9870e61e811b        14 hours ago        331MB
jenkins                           v2                  f9515dee15b6        14 hours ago        1.33GB
jenkins                           v1                  e8b3509a7c25        17 hours ago        899MB
registry                          latest              2e2f252f3c88        6 days ago          33.3MB
centos                            latest              5182e96772bf        6 weeks ago         200MB

push到仓库

$ docker push 192.168.3.69:5000/system/centos

7.2 第三方仓库harbor

7.2.1 下载hearbor

Harbor官网:https://goharbor.io/

Hearbor 下载地址: https://github.com/goharbor/harbor/releases下载完成上传到服务器并解压

$ cd /application/
$ rz                               #上传镜像
$ tar xf harbor-offline-installer-v1.5.3.tgz 
$ ll hearbor
drwxr-xr-x. 3 root root        22 Sep 18 15:11 common
-rw-r--r--. 1 root root      1185 Sep 12 14:19 docker-compose.clair.yml
-rw-r--r--. 1 root root      1725 Sep 12 14:19 docker-compose.notary.yml
-rw-r--r--. 1 root root      3596 Sep 12 14:19 docker-compose.yml
drwxr-xr-x. 3 root root      4096 Sep 12 14:19 ha
-rw-r--r--. 1 root root      6956 Sep 12 14:19 harbor.cfg
-rw-r--r--. 1 root root 915878468 Sep 12 14:21 harbor.v1.5.3.tar.gz
-rwxr-xr-x. 1 root root      5773 Sep 12 14:19 install.sh
-rw-r--r--. 1 root root     10764 Sep 12 14:19 LICENSE
-rw-r--r--. 1 root root       482 Sep 12 14:19 NOTICE
-rw-r--r--. 1 root root   1247461 Sep 12 14:19 open_source_license
-rwxr-xr-x. 1 root root     27840 Sep 12 14:19 prepare  

7.2.2 安装依赖软件并配置

$ yum -y install epel-release       #安装epel源
$ yum -y install python-pip         #安装pip
$ pip install docker-compose        #安装docker-compose
$ docker rm $(docker ps -a -q)      #删除已经停止的所有容器,生产环境不要这样干,这是为了测试方便

安装启动停止均在/application/harbor/目录下执行

编辑配置文件

$ cd /application/harbor/
$ vim harbor.cfg
hostname = 192.168.3.69          #修改为自己主机ip地址

添加信任为192.168.3.69默认的80端口

$ vim /etc/docker/daemon.json      
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries" : ["http://192.168.3.69"]
}
$ systemctl restart docker #重启docker

执行安装

$ ./install.sh

查看容器状态

$ docker-compose ps    
 Name                     Command                  State                                    Ports                              
---------------------------------------------------------------------------------------------------harbor-adminserver   /harbor/start.sh                 Up (healthy)                                                                   
harbor-db            /usr/local/bin/docker-entr ...   Up (healthy)   3306/tcp                                                        
harbor-jobservice    /harbor/start.sh                 Up                                                                             
harbor-log           /bin/sh -c /usr/local/bin/ ...   Up (healthy)   127.0.0.1:1514->10514/tcp                                       
harbor-ui            /harbor/start.sh                 Up (healthy)                                                                   
nginx                nginx -g daemon off;             Up (healthy)   0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:80->80/tcp
redis                docker-entrypoint.sh redis ...   Up             6379/tcp                                                        
registry             /entrypoint.sh serve /etc/ ...   Up (healthy)   5000/tcp

docker-compose参数

docker-compose status #查看使用命令参数
docker-compose stop   #停止
docker-compose start  #启动

7.2.3 浏览器测试

浏览器访问: http://192.168.3.69    账号:admin  密码:Harbor12345

修改管理员密码

新建项目

选择不公开

客户端上传镜像三部曲

1.先登录

$ docker login 192.168.3.69  #输入用户名和密码同web端一样
Username: admin
Password:

2.打标签

$ docker tag system/centos:v2 192.168.3.69/system/centos

3.docker push

$ docker push 192.168.3.69/system/centos

Web界面查看仓库中已经有了镜像

参考文献:

https://docker_practice.gitee.io/basic_concept/image.html

原文地址:https://www.cnblogs.com/blsnt/p/9884418.html