前言:

Docker是1种小型虚拟主机,那么Docker和KVM虚拟机主机之间有什么区别和联系?Docker的应用场景是什么呢? 

Docker的本质是基于

  • Linux内核的Namespace和Cgroup特性,Namespace实现了环境隔离、Cgroup实现了系统资源限制
  • UnionFS实现了镜像分层打包

Docker比虚拟机:更加轻量级、秒级即可启动、只要操作系统支持LXC技术,有doker服务,就可以跨主机到处运行。

Docker镜像的分层设计思想,给我感觉就是非常灵活,非常适用于To B的产品的部署;

一、Docker是什么以及和KVM的区别

1.Docker概念

Docker基于Linux内核的2大特性实现

  • Namespace:隔离进程的UTS、IPC、PID、Network、Mount、User系统资源。
  • Cgroup:ControlGroups把进程放到组里面,通过对组设置权限,进而限制进程对系统资源的使用。

2.Docker的设计理念

快速地构建(build)、运输(ship)、运行(running)系统环境

1个容器=1个在前台运行的进程。如果我就想在同1个容器里运行多个进程呢?那就让1个supervisor管理N个进程。

3.docker的架构

docker是C/S 架构 docker server 是服务端,我们执行的docker命令就是操作客户端;

[root@localhost zhanggen]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

-----------------------------------------------------------
[root@localhost zhanggen]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2019-03-20 15:19:16 CST; 6min ago
     Docs: https://docs.docker.com
 Main PID: 55180 (dockerd)
   Memory: 75.6M
   CGroup: /system.slice/docker.service
           └─55180 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
组成部分

f

4.论docker and kvm

Docker Server 挂了所有的docker容器都会挂掉 (kvm的管理软件 和libvirtd完全隔离)

kvm是在内核级别完全虚拟化出来的虚拟机 虚拟机之间完全隔离

docker 容器是在操作系统层面进行的资源的隔离

Docker和KVM都可以进行状态的回滚

 

5.docker的优势和应用场景

简化了系统配置、减少了代码和系统环境间的依赖性(运行别人的代码还要部署别人的运行环境)
代码流水线管理 代码开发---->代码测试----》代码到生产 一个docker容器搞定
减少开发部署系统环境工作,提高开发效率。
docker容器和虚拟机相比可以快速得运行起来

面向产品:把自己的系统运行环境+代码打包进docker容器,直接完产品交付;
面向开发:做为一个python开发我再也不用去装什么Python3、pip、Nginx了,我只关心我的代码怎么写?
面向测试:测试的时候不用搭建多套系统环境了
面向运行:环境一致性,系统环境可以回滚
面向架构:自动化扩容

6.Centos7 yum安装docker

{
"registry-mirrors": ["https://pee6w651.mirror.aliyuncs.com"]
}
换个阿里云的docker源 vim /etc/docker/daemon.json

 

查看docker日志

这个很关键,遇到报错一定不要心浮气躁,也不要直接去百度搜索报错内容, 科学的做法是:看日志-----》锁定问题-----》解决问题

[root@localhost zhanggen]# journalctl -xe
Mar 20 14:28:31 localhost.localdomain polkitd[582]: Registered Authentication Agent for unix-process:55506:719734 (system bus name :1.510 [/
Mar 20 14:28:31 localhost.localdomain systemd[1]: Starting Docker Storage Setup...
-- Subject: Unit docker-storage-setup.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker-storage-setup.service has begun starting up.
Mar 20 14:28:31 localhost.localdomain container-storage-setup[55512]: INFO: Volume group backing root filesystem could not be determined
Mar 20 14:28:31 localhost.localdomain systemd[1]: Started Docker Storage Setup.
-- Subject: Unit docker-storage-setup.service has finished start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker-storage-setup.service has finished starting up.
-- 
-- The start-up result is done.
Mar 20 14:28:31 localhost.localdomain systemd[1]: Starting Docker Application Container Engine...
-- Subject: Unit docker.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker.service has begun starting up.
Mar 20 14:28:31 localhost.localdomain dockerd-current[55557]: unable to configure the Docker daemon with file /etc/docker/daemon.json: inval
Mar 20 14:28:31 localhost.localdomain systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE
Mar 20 14:28:31 localhost.localdomain systemd[1]: Failed to start Docker Application Container Engine.
-- Subject: Unit docker.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker.service has failed.
-- 
-- The result is failed.
Mar 20 14:28:31 localhost.localdomain systemd[1]: Unit docker.service entered failed state.
Mar 20 14:28:31 localhost.localdomain systemd[1]: docker.service failed.
Mar 20 14:28:31 localhost.localdomain polkitd[582]: Unregistered Authentication Agent for unix-process:55506:719734 (system bus name :1.510,
journalctl -xe 查看docker日志

 

查看docker版本

[root@localhost zhanggen]# docker version
Client:
 Version:         1.13.1
 API version:     1.26
 Package version: 
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
docker version

 

源码安装 

#!/bin/bash
project_volume=/mingde_project
image_name="modelsystem:2.0"
container_name="modelsystem"

read -r -p "Are you sure that docker have not been installed? [Yes/No] " confirmation1

echo $confirmation1
if [[ "$confirmation1" != "Yes" ]];then
echo "Bye Bye.."
exit 0
fi
\cp -rf ../plugins/docker/* /usr/bin/ 
\cp -rf ../plugins/docker.service /usr/lib/systemd/system/
mkdir -p $project_volume && \cp -rf ../project/* $project_volume
systemctl daemon-reload
systemctl start docker
echo "Docker have installed successfully"

for i in ../images/*;do docker load < $i;done
#docker/docker load < ../images/modelsystem.tar
check_conflict=$(docker ps -a -q --filter ancestor=$image_name)
if [[ $check_conflict != "" ]]
then
docker rm -f $(docker ps -a -q --filter ancestor=$image_name)
fi
docker run -d -p 8099:8099 -v $project_volume:/mingde --name $container_name $image_name
install.sh

 

卸载docker

#!/bin/sh
/usr/bin/systemctl daemon-reload
echo '关闭docker服务....'
echo '删除docker.service...'
echo '删除docker文件...'
rm -rf /mingde_project
rm -rf /usr/lib/systemd/system/docker.service
for file in ../plugins/docker/*
do rm -rf /usr/bin/${file##*/}
done
#rm -rf /usr/lib/systemd/system/docker.service
#rm -rf /usr/bin/containerd
#rm -rf /usr/bin/containerd-shim
#rm -rf /usr/bin/ctr
#rm -rf /usr/bin/docker
#rm -rf /usr/bin/dockerd
#rm -rf /usr/bin/docker-init
#rm -rf /usr/bin/docker-proxy
#rm -rf /usr/bin/runc
echo '删除docker文件...'
echo '重新加载配置文件'
/usr/bin/systemctl daemon-reload
echo '卸载成功...'
ininstall

 

7.离线二进制安装docker

目前我们主要开展To B业务,客户环境大多都是在内网,那么离线安装docker就成了我需要解决的问题;

我的要求:最大限度地保持客户环境安装目录的整洁和规范,把dockerd做成系统服务,可通过systemctl 进行启停管理并开机自启动。

以下是我的部署方案:

  1. 把docker二进制包都放在了自定义的目录下(/mingde/docker)而不是/usr/bin,
  2. 在/etc/profile.d目录下新增系统环境变量配置;
  3. 在systemd的docker.service中新增Environment=PATH=$PATH:/mingde/docker配置,以便让sysytemd启动dockerd前,可以加载到我在步骤2设置的系统环境变量。

/etc/profile.d/docker.sh 

export PATH=$PATH:/mingde/docker
export PATH

/etc/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
Environment=PATH=$PATH:/mingde/docker
ExecStart=/mingde/docker/dockerd --selinux-enabled=false --iptables=false
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target 

最后重新加载systemd,然后把dockerd服务变成系统服务。

[root@localhost docker]# ls
containerd  containerd-shim  ctr  docker  dockerd  docker-init  docker-proxy  runc
[root@localhost docker]# pwd
/mingde/docker
[root@localhost docker]# systemctl daemon-reload 
[root@localhost docker]# systemctl start docker
[root@localhost docker]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /etc/systemd/system/docker.service.
[root@localhost docker]# reboot

 

把redis也做成可以被systemct启动的进程

/etc/systemd/system/redis.service

[Unit]
Description=redis
After=network.target

[Service]
PIDFile=/var/run/redis_6379.pid
ExecStart=/mingde/redis-4.0.10/src/redis-server  /mingde/redis-4.0.10/redis.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

8.docker的组件

docker的组件分为:镜像image、容器container 、仓库(repository)

镜像:所有的docker容器都是由镜像启动构建的

仓库:集中存放镜像,用户同网络访问仓库获得想要镜像 DockerHub,就是GitHub一样;

容器:就是由镜像创建的实例(简化版的Linux环境)

9.加速镜像源访问

"https://ustc-edu-cn.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://registry.aliyuncs.com"

二、docker快速入门

从docker的三大组件开始快速入门docker;

1.docker镜像管理

去docker Hub 上搜素镜像

[root@localhost zhanggen]# docker search centos
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
centos                             The official build of CentOS.                   5261                [OK]                
ansible/centos7-ansible            Ansible on Centos7                              121                                     [OK]
jdeathe/centos-ssh                 CentOS-6 6.10 x86_64 / CentOS-7 7.5.1804 x86…   109                                     [OK]
consol/centos-xfce-vnc             Centos container with "headless" VNC session…   83                                      [OK]
imagine10255/centos6-lnmp-php56    centos6-lnmp-php56                              52                                      [OK]
centos/mysql-57-centos7            MySQL 5.7 SQL database server                   49                                      
tutum/centos                       Simple CentOS docker image with SSH access      44                                      
gluster/gluster-centos             Official GlusterFS Image [ CentOS-7 +  Glust…   40                                      [OK]
openshift/base-centos7             A Centos7 derived base image for Source-To-I…   39                                      
centos/postgresql-96-centos7       PostgreSQL is an advanced Object-Relational …   37                                      
kinogmt/centos-ssh                 CentOS with SSH                                 26                                      [OK]
centos/httpd-24-centos7            Platform for running Apache httpd 2.4 or bui…   22                                      
openshift/jenkins-2-centos7        A Centos7 based Jenkins v2.x image for use w20                                      
centos/php-56-centos7              Platform for building and running PHP 5.6 ap…   20                                      
pivotaldata/centos-gpdb-dev        CentOS image for GPDB development. Tag names…   10                                      
openshift/wildfly-101-centos7      A Centos7 based WildFly v10.1 image for use …   6                                       
openshift/jenkins-1-centos7        DEPRECATED: A Centos7 based Jenkins v1.x ima…   4                                       
darksheer/centos                   Base Centos Image -- Updated hourly             3                                       [OK]
pivotaldata/centos-mingw           Using the mingw toolchain to cross-compile t…   2                                       
pivotaldata/centos                 Base centos, freshened up a little with a Do…   2                                       
pivotaldata/centos-gcc-toolchain   CentOS with a toolchain, but unaffiliated wi…   1                                       
blacklabelops/centos               CentOS Base Image! Built and Updates Daily!     1                                       [OK]
openshift/wildfly-81-centos7       A Centos7 based WildFly v8.1 image for use w1                                       
smartentry/centos                  centos with smartentry                          0                                       [OK]
jameseckersall/sonarr-centos       Sonarr on CentOS 7     
docker search centos

 去docker hub上下载镜像

[root@localhost zhanggen]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete 
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest
[root@localhost zhanggen]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        6 days ago          2
docker pull centos

 docker镜像保存为文件(镜像导出)

[root@localhost zhanggen]# docker save -o Centos.tart centos
[root@localhost zhanggen]# ls
Centos.tart  Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos
docker save -o Centos.tar

文件还原为docker镜像(镜像导入)

[root@localhost zhanggen]# docker load --input Centos.tar
Loaded image: centos:latest
[root@localhost zhanggen]# 
docker load --input Centos.tar

 删除docker镜像

[root@localhost zhanggen]# docker rmi -f centos
Untagged: centos:latest
Untagged: centos@sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
[root@localhost zhanggen]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              9f38484d220f        6 days ago          202MB
[root@localhost zhanggen]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest
[root@localhost zhanggen]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        6 days ago          202MB
[root@localhost zhanggen]#
docker rmi -f centos

 

2.docker容器管理

镜像的管理就是这些,主要还是自己可以构建镜像。

docker run -d -p 3306:3306 --privileged=true --name=MysqlServer --restart=always -e MYSQL_ROOT_PASSWORD=zhanggen@123 -v $PWD/logs:/var/log/docker -v $PWD/data:/var/lib/mysql -v $PWD/my.cnf:/etc/mysql/my.cnf -v /etc/localtime:/etc/localtime:ro mysql:5.7

------------------------------------------------------

[root@localhost zhanggen]# docker run centos /bin/echo 'Hellow World!'
WARNING: IPv4 forwarding is disabled. Networking will not work.
Hellow World!!
[root@localhost zhanggen]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@localhost zhanggen]# 

PS:为什么 我运行了一个 echo 程序  docker容器就马上停止了?

因为docker容器默认会在docker容器的前台运行1个进程,这个进程结束docker,容器也随之停止了;(也许这就是它的一次性设计理念吧。。)

是不是很纳闷 为什么docker运行的进程退出,容器怎么就退出了? 这就是docker的理念---不可变基础设施理念!

docker就是给进程做隔离使用的,不同于虚拟机,虚拟机才是给操作系统做隔离使用的;

docker只是个容器 不是虚拟机!

[root@261f12e2d6e4 /]# cat /proc/cpuinfo 
processor    : 0
vendor_id    : GenuineIntel
cpu family    : 6
model        : 78
model name    : Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
stepping    : 3
microcode    : 0x88
cpu MHz        : 2591.294
cache size    : 4096 KB
physical id    : 0
siblings    : 1
core id        : 0
cpu cores    : 1
apicid        : 0
initial apicid    : 0
fpu        : yes
fpu_exception    : yes
cpuid level    : 22
wp        : yes
flags        : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch arat fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec
bogomips    : 5184.39
clflush size    : 64
cache_alignment    : 64
address sizes    : 43 bits physical, 48 bits virtual
power management:
你进入容器千万不要感觉是进入了虚拟机

 

运行新的docker   --name (容器名称) mydocker    -t (terminal 打开一个终端)    -i (std input 打开标准输入 )  

[root@localhost zhanggen]# docker run  --name mydocker -t -i centos /bin/bash
WARNING: IPv4 forwarding is disabled. Networking will not work.
[root@261f12e2d6e4 /]# 
docker run --name mydocker -t -i centos /bin/bash

 

 启动一个关闭的docker容器

[root@localhost zhanggen]# docker start mydocker
mydocker
[root@localhost zhanggen]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
261f12e2d6e4        centos              "/bin/bash"              About an hour ago   Up 7 seconds                                       mydocker
d0dd5f7a79e8        centos              "/bin/echo 'hellow I…"   About an hour ago   Exited (0) About an hour ago                       sharp_chandrasekhar
docker start mydocker

 

 进如正在运行的容器看看

[root@localhost zhanggen]# docker attach mydocker
[root@261f12e2d6e4 /]# 
docker attach mydocker

 

删除所有容器

[root@localhost zhanggen]# docker rm -f e627d59e818c 
e627d59e818c
[root@localhost zhanggen]# docker rm -f d0dd5f7a79e8 
d0dd5f7a79e8
[root@localhost zhanggen]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@localhost zhanggen]# 
docker rm -f e627d59e818c
[root@localhost /]# docker rm $(docker ps -aq)
eecdba33cb61
b2da31fc0100
06afb1402c3e
[root@localhost /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@localhost /]# 
docker rm $(docker ps -aq) 一次性删除所有

 

删除已经停止的容器和镜像

docker rm `docker ps -a|grep Exited|awk '{print $1}'`
docker rmi `docker images | grep "none" | awk '{print $3}'`

3.进入正在运行中docker容器的2种最佳方式

查看正在运行容器的进程

[root@localhost zhanggen]# docker inspect -f "{{.State.Pid}}" mydocker
64721
docker inspect -f "{{.State.Pid}}" mydocker

通过进程ID反复进入docker容器

[root@localhost zhanggen]# nsenter -t 64721 -m -u -i -n -p
-bash: __vte_prompt_command: command not found
[root@261f12e2d6e4 /]# 
nsenter -t 64721 -m -u -i -n -p

为什么通过 nsenter -t 64721 -m -u -i -n -p 进入docker容器exit之后不退出?

其实就是多开了一个bash进程

[root@localhost zhanggen]# nsenter -t 64721 -m -u -i -n -p
-bash: __vte_prompt_command: command not found
[root@261f12e2d6e4 /]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 08:43 pts/0    00:00:00 /bin/bash
root         28      0  0 08:49 pts/0    00:00:00 -bash        #其实就是多开了1个bash进程
root         42     28  0 08:52 pts/0    00:00:00 ps -ef
-bash: __vte_prompt_command: command not found
[root@261f12e2d6e4 /]# exit
logout
[root@localhost zhanggen]# nsenter -t 64721 -m -u -i -p
-bash: __vte_prompt_command: command not found
[root@261f12e2d6e4 /]# 
nsenter -t 64721 -m -u -i -n -p

docker exec 在不进入docker容器前提下 执行1个命令(一个程序)

root@localhost zhanggen]# docker exec mydocker whoami
root
[root@localhost zhanggen]# docker exec mydocker pwd
/
[root@localhost zhanggen]# docker exec mydocker ls
anaconda-post.log
bin
dev
etc
docker exec mydocker whoami

比如我们使用了某个镜像启动了docker容器,但是没有运行成功,需要额外安装一些依赖。

[root@VM-0-5-centos /]# docker run -d -p 8092:8099 -v /modManagerProject:/mingde --name ModManagerProject modelsystem:2.0
0ddfa1ad08f8b210df4f60da96d2c35ec78cdf4ddc55de66cd20a6eea7dc5110
[root@VM-0-5-centos /]# docker exec ModManagerProject pip install Flask-SQLAlchemy==2.5.1
[root@VM-0-5-centos /]# docker exec ModManagerProject pip install flask_cors
[root@VM-0-5-centos /]# docker exec ModManagerProject ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:37 ?        00:00:00 /bin/sh -c sh /root/scripts/run.sh
root         6     1  0 07:37 ?        00:00:00 sh /root/scripts/run.sh
root         7     6  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root         8     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root         9     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        10     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        11     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        12     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        13     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        14     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        15     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        16     7  0 07:37 ?        00:00:00 uwsgi --ini /mingde/uwsgi/uwsgi.ini
root        35     0  0 07:39 ?        00:00:00 ps -ef
[root@VM-0-5-centos /]# docker exec ModManagerProject uwsgi --reload /mingde/uwsgi/uwsgi.ini
[root@VM-0-5-centos /]# docker stop  ModManagerProject 
ModManagerProject
[root@VM-0-5-centos /]# docker start ModManagerProject 
ModManagerProject

通过dcker exec 打开bash程序之间进入docker容器

[root@localhost zhanggen]# docker exec -it mydocker /bin/bash
[root@261f12e2d6e4 /]# exit 
exit
[root@localhost zhanggen]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        6 days ago          202MB
[root@localhost zhanggen]# 
docker exec -it mydocker

 在宿主机后台运行docker容器

[root@localhost zhanggen]# docker run --name my_nginx -d nginx
WARNING: IPv4 forwarding is disabled. Networking will not work.
3aafe4fe15248ec4cd526a1873b6fc1e50b9c87926f6504755ebd021f76f5d61
[root@localhost zhanggen]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3aafe4fe1524        nginx               "nginx -g 'daemon of…"   4 seconds ago       Up 3 seconds        80/tcp              my_nginx
[root@localhost zhanggen]# 
后台运行docker容器

 

4.DockerPortainer

Docker提供了图形化界面的方式来管理docker容器;

1 下载镜像

docker pull portainer/portainer

2.2 启动portainer

#创建文件存储文件
docker volume create portainer_data
#创建并启动容器 --restart=always   开机自动启动`
docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

2.3 访问:ip:9000 第一次登陆需要设置登陆密码,密码不得少于8位

 

 

 

二、docker的网络访问

As a senior Web application developer,how to access it  if I`ve I developed a  Web application in docker container. 

我在docker里面写了个Django程序,我怎么访问它的8001端口呢?这就需要给docker容器开通网络访问功能;

 docker安装之后会自动创建一个 docker0的桥接网卡

[root@localhost zhanggen]# ifconfig 
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:b4ff:fe4c:7745  prefixlen 64  scopeid 0x20<link>
        ether 02:42:b4:4c:77:45  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3  bytes 258 (258.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 
docker0

docker的网络就是通过docker0这个网桥进行 NAT 转换到docker容器的

 

配置centos7开启IPV4转发并重启网卡

net.ipv4.ip_forward=1
vim /usr/lib/sysctl.d/00-system.conf

 开启随机端口访问

[root@localhost zhanggen]# vim /usr/lib/sysctl.d/00-system.conf
[root@localhost zhanggen]# docker run -d -P nginx
06afb1402c3eb177dbae8b72cd94be90c63713ce73a1bac7ab8f85ecdae50caa
[root@localhost zhanggen]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
06afb1402c3e        nginx               "nginx -g 'daemon of…"   11 seconds ago      Up 9 seconds        0.0.0.0:32769->80/tcp   zen_hellman
docker run -d -P nginx

指定端口进行访问

[root@localhost zhanggen]# docker run --name mydocker -d -p 8001:80 nginx
b2da31fc010033f378e0930a2b77cec498ba6cbc1d288353562e3d0c6b23ae3c
[root@localhost zhanggen]# 
docker run --name mydocker -d -p 8001:80 nginx

 

 

三、docker的数据管理

说到docker的数据管理,首先得清楚docker镜像的分层存储结构?

docker镜像是采用分层结构存储的,Docker镜像是只读、不可写的,docker容器在docker镜像之上是可写的,用户在docker容器的基础上操作之后commit 修改成只读镜像,盖了一层再来一层....

 

As I mentioned docker 采用的是一种开箱  既用-->用完--->即仍 的一次性理念,那么在docker运行中产生的一些日志..如何持久化?有一下两种方式;

 

 

1.数据卷

我们把宿主机中的一个目录mount 到docker容器的一个目录里面,docker容器运行中产生的数据写得宿主机的目录里;

[root@localhost zhanggen]# docker run -d --name nginx-volume -v /data nginx
70d688ad2c40e4490d05da0fa8bdbc0cc342315f1bbc61e7a63d4422832512c5
docker run -d --name nginx-volume -v /data nginx

 如果你想知道docker容器的 /data目录到底挂载到宿主机的哪个目录上了?

[root@localhost zhanggen]# docker run -d --name nginx-volume -v /data nginx
70d688ad2c40e4490d05da0fa8bdbc0cc342315f1bbc61e7a63d4422832512c5
[root@localhost zhanggen]# docker inspect -f {{.Mounts}} nginx-volume
[{volume 4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd /var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data /data local  true }]
[root@localhost zhanggen]# ls
Centos.tart  Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos
[root@localhost zhanggen]# cd /var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data 
[root@localhost _data]# pwd
/var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data
[root@localhost _data]# ls
[root@localhost _data]# 
docker run -d --name nginx-volume -v /data nginxdocker & inspect -f {{.Mounts}} nginx-volume
root@localhost _data]# docker inspect -f {{.Mounts}} nginx-volume
[{volume 4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd /var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data /data local  true }]
[root@localhost _data]# pwd
/var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data
[root@localhost _data]# touch 草你妈王X聪
[root@localhost _data]# docker exec -it nginx-volume /bin/bash
root@70d688ad2c40:/# ls   
bin  boot  data  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@70d688ad2c40:/# cd d 
data/ dev/  
root@70d688ad2c40:/# cd data/
root@70d688ad2c40:/data# ls
FUCK_WANGSICHONGTAMA  ??????????????????
root@70d688ad2c40:/data# 
验证一下docker容器里面的/data目录是否和宿主机的目录关联在一起了

在生产环境我们一般会自己创建一个目录 在挂载到docker目录里

[root@localhost _data]# docker run -d --name nginx-volume -v  /data/docker/volume-nginx/:/data nginx
09fc60548e01040805d6de92ace28062055a91eb832129b075e7e2605c149b45
[root@localhost _data]# docker exec -it nginx-volume /bin/bash
root@09fc60548e01:/# ls
bin  boot  data  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@09fc60548e01:/# cd data/
root@09fc60548e01:/data# ls
root@09fc60548e01:/data# echo 'sss' > Martin.txt
root@09fc60548e01:/data# ls
Martin.txt
root@09fc60548e01:/data# cat Martin.txt 
sss
root@09fc60548e01:/data# exit
exit
[root@localhost _data]# pwd
/var/lib/docker/volumes/4fbd49850452bcca0a867f09776f716b137c5f13f5a8b8a3a5e84e26496f9fcd/_data
[root@localhost _data]# cd /data/docker/volume-nginx/
[root@localhost volume-nginx]# ls
Martin.txt
[root@localhost volume-nginx]# cat Martin.txt 
sss
[root@localhost volume-nginx]# 
docker run -d --name nginx-volume -v /data/docker/volume-nginx/:/data nginx

 

 2.数据卷容器

 在容器是否运行、关闭的状态下,容器之间都可以共享容器卷数据;(NFS)

  使用--volumes-from 指定要和哪个容器共享容器卷

[root@localhost volume-nginx]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
09fc60548e01        nginx               "nginx -g 'daemon of…"   16 minutes ago      Up 16 minutes       80/tcp              nginx-volume
[root@localhost volume-nginx]# docker run -it --name volume-test --volumes-from nginx-volume centos /bin/bash
[root@c16407be0cf4 /]# ls data/
Martin.txt
[root@c16407be0cf4 /]# exit
exit
[root@localhost volume-nginx]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
09fc60548e01        nginx               "nginx -g 'daemon of…"   18 minutes ago      Up 18 minutes       80/tcp              nginx-volume
[root@localhost volume-nginx]# docker exec -it nginx-volume /bin/bash
root@09fc60548e01:/# ls data/
Martin.txt
root@09fc60548e01:/# 
docker run -it --name volume-test --volumes-from nginx-volume centos /bin/bash

 生成环境:一般都会起 1个专门的容器挂载到宿主机的1个目录上,以后其他容器都 通过 --volumes-from 该容器   的形式来达到容器卷数据共享的效果;

 

 

四、docker镜像的构建

docker镜像是docker可以传播的介质,那么如何制作自己的docker镜像?分为如下2种方式:

手动构建

自己在容器里面做操作,操作完毕之后,commit成自己的镜像,

Dockerfile构建

以文件的形式执行力里面的命令进行快速构建,比较自动化化,相比容器较为轻量也更易于传播;

最后还会谈谈我在生产环境中使用dockerfile的经验。

 

1.手动创建镜像

docker run --name mynginx -it centos    #使用基础镜像 centos 运行1个名为 mynginx 的容器
vim /etc/nginx/nginx.conf 进入docker容器,修改Nginx配置文件

exit 退出容器

docker ps -a                                 #查看刚刚exit的容器
docker commit -m 'MyNginx' cd35 zhanggen/mynginx:v1              #commit把停止的容器提交到本地分支
docker images                                                     #制作完成
docker run --name mynginxv1 -d -p 81:80 zhanggen/mynginx:v1 nginx #启动

PS:麻蛋发现自己制作的docker镜像启动不起来咋办?

查看容器启动的报错日志----》重新进入容器-----》检查操作,修改---》重新提交本地分支-----》重新启动

docker ps -a                                   #查看启动失败的镜像ID
docker logs container_id                                          #查看报错日志
docker run -it zhanggen/mynginx:v1 /bin/bash                      #重新运行 该镜像进去修改
docker commit -m 'MyNginx' cd35 zhanggen/mynginx:v1               #修改完毕重新提交到本地分支
docker run --name mynginxv1 -d -p 81:80 zhanggen/mynginx:v1 nginx #重新启动镜像
自制镜像无法启动攻略

 

2.Docker file构建

Docker file语法

OM centos
MAINTAINER Martin.Zhang
RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
RUN yum install -y nginx && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
ADD index.html /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx"]
Dockerfile
<html>
<body>
<h1>ssssssssss!!!!</h1>
</body>
</html>
index.html
[root@localhost nginx]# pwd
/dockerfile/nginx
[root@localhost nginx]# ls
Dockerfile  index.html
[root@localhost nginx]# docker build -t mynginx:v2 .
Sending build context to Docker daemon  3.072kB
Step 1/8 : FROM centos
 ---> 9f38484d220f
Step 2/8 : MAINTAINER Martin.Zhang
 ---> Running in be6d86ffa2a9
Removing intermediate container be6d86ffa2a9
 ---> 0dc16c8dadcc
Step 3/8 : RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
 ---> Running in 3ce6b480a0a2
warning: /var/tmp/rpm-tmp.qHH8Wh: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY
Retrieving http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
Preparing...                          ########################################
Updating / installing...
epel-release-7-11                     ########################################
Removing intermediate container 3ce6b480a0a2
 ---> 6b2b42a8e360
Step 4/8 : RUN yum install -y nginx && yum clean all
 ---> Running in 3e228aab6696
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: mirrors.aliyun.com
 * epel: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.12.2-2.el7 will be installed
--> Processing Dependency: nginx-all-modules = 1:1.12.2-2.el7 for package: 1:nginx-1.12.2-2.el7.x86_64
--> Processing Dependency: nginx-filesystem = 1:1.12.2-2.el7 for package: 1:nginx-1.12.2-2.el7.x86_64
--> Processing Dependency: nginx-filesystem for package: 1:nginx-1.12.2-2.el7.x86_64
--> Processing Dependency: openssl for package: 1:nginx-1.12.2-2.el7.x86_64
--> Processing Dependency: libprofiler.so.0()(64bit) for package: 1:nginx-1.12.2-2.el7.x86_64
--> Running transaction check
---> Package gperftools-libs.x86_64 0:2.6.1-1.el7 will be installed
---> Package nginx-all-modules.noarch 1:1.12.2-2.el7 will be installed
--> Processing Dependency: nginx-mod-http-geoip = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
--> Processing Dependency: nginx-mod-http-image-filter = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
--> Processing Dependency: nginx-mod-http-perl = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
--> Processing Dependency: nginx-mod-http-xslt-filter = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
--> Processing Dependency: nginx-mod-mail = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
--> Processing Dependency: nginx-mod-stream = 1:1.12.2-2.el7 for package: 1:nginx-all-modules-1.12.2-2.el7.noarch
---> Package nginx-filesystem.noarch 1:1.12.2-2.el7 will be installed
---> Package openssl.x86_64 1:1.0.2k-16.el7_6.1 will be installed
--> Processing Dependency: openssl-libs(x86-64) = 1:1.0.2k-16.el7_6.1 for package: 1:openssl-1.0.2k-16.el7_6.1.x86_64
--> Processing Dependency: make for package: 1:openssl-1.0.2k-16.el7_6.1.x86_64
--> Running transaction check
---> Package make.x86_64 1:3.82-23.el7 will be installed
---> Package nginx-mod-http-geoip.x86_64 1:1.12.2-2.el7 will be installed
--> Processing Dependency: GeoIP for package: 1:nginx-mod-http-geoip-1.12.2-2.el7.x86_64
--> Processing Dependency: libGeoIP.so.1()(64bit) for package: 1:nginx-mod-http-geoip-1.12.2-2.el7.x86_64
---> Package nginx-mod-http-image-filter.x86_64 1:1.12.2-2.el7 will be installed
--> Processing Dependency: gd for package: 1:nginx-mod-http-image-filter-1.12.2-2.el7.x86_64
--> Processing Dependency: libgd.so.2()(64bit) for package: 1:nginx-mod-http-image-filter-1.12.2-2.el7.x86_64
---> Package nginx-mod-http-perl.x86_64 1:1.12.2-2.el7 will be installed
--> Processing Dependency: perl >= 5.006001 for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(:MODULE_COMPAT_5.16.3) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(Exporter) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(XSLoader) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(constant) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(strict) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: perl(warnings) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
--> Processing Dependency: libperl.so()(64bit) for package: 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64
---> Package nginx-mod-http-xslt-filter.x86_64 1:1.12.2-2.el7 will be installed
--> Processing Dependency: libxslt.so.1(LIBXML2_1.0.11)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64
--> Processing Dependency: libxslt.so.1(LIBXML2_1.0.18)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64
--> Processing Dependency: libexslt.so.0()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64
--> Processing Dependency: libxslt.so.1()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64
---> Package nginx-mod-mail.x86_64 1:1.12.2-2.el7 will be installed
---> Package nginx-mod-stream.x86_64 1:1.12.2-2.el7 will be installed
---> Package openssl-libs.x86_64 1:1.0.2k-16.el7 will be updated
---> Package openssl-libs.x86_64 1:1.0.2k-16.el7_6.1 will be an update
--> Running transaction check
---> Package GeoIP.x86_64 0:1.5.0-13.el7 will be installed
---> Package gd.x86_64 0:2.0.35-26.el7 will be installed
--> Processing Dependency: libpng15.so.15(PNG15_0)(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libjpeg.so.62(LIBJPEG_6.2)(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libpng15.so.15()(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libjpeg.so.62()(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libfreetype.so.6()(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libfontconfig.so.1()(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libXpm.so.4()(64bit) for package: gd-2.0.35-26.el7.x86_64
--> Processing Dependency: libX11.so.6()(64bit) for package: gd-2.0.35-26.el7.x86_64
---> Package libxslt.x86_64 0:1.1.28-5.el7 will be installed
---> Package perl.x86_64 4:5.16.3-294.el7_6 will be installed
--> Processing Dependency: perl(Socket) >= 1.3 for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Scalar::Util) >= 1.10 for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl-macros for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(threads::shared) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(threads) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Time::Local) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Time::HiRes) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Storable) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Socket) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Scalar::Util) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Pod::Simple::XHTML) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Pod::Simple::Search) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Getopt::Long) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Filter::Util::Call) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(File::Temp) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(File::Spec::Unix) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(File::Spec::Functions) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(File::Spec) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(File::Path) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Cwd) for package: 4:perl-5.16.3-294.el7_6.x86_64
--> Processing Dependency: perl(Carp) for package: 4:perl-5.16.3-294.el7_6.x86_64
---> Package perl-Exporter.noarch 0:5.68-3.el7 will be installed
---> Package perl-constant.noarch 0:1.27-2.el7 will be installed
---> Package perl-libs.x86_64 4:5.16.3-294.el7_6 will be installed
--> Running transaction check
---> Package fontconfig.x86_64 0:2.13.0-4.3.el7 will be installed
--> Processing Dependency: fontpackages-filesystem for package: fontconfig-2.13.0-4.3.el7.x86_64
--> Processing Dependency: dejavu-sans-fonts for package: fontconfig-2.13.0-4.3.el7.x86_64
---> Package freetype.x86_64 0:2.8-12.el7_6.1 will be installed
---> Package libX11.x86_64 0:1.6.5-2.el7 will be installed
--> Processing Dependency: libX11-common >= 1.6.5-2.el7 for package: libX11-1.6.5-2.el7.x86_64
--> Processing Dependency: libxcb.so.1()(64bit) for package: libX11-1.6.5-2.el7.x86_64
---> Package libXpm.x86_64 0:3.5.12-1.el7 will be installed
---> Package libjpeg-turbo.x86_64 0:1.2.90-6.el7 will be installed
---> Package libpng.x86_64 2:1.5.13-7.el7_2 will be installed
---> Package perl-Carp.noarch 0:1.26-244.el7 will be installed
---> Package perl-File-Path.noarch 0:2.09-2.el7 will be installed
---> Package perl-File-Temp.noarch 0:0.23.01-3.el7 will be installed
---> Package perl-Filter.x86_64 0:1.49-3.el7 will be installed
---> Package perl-Getopt-Long.noarch 0:2.40-3.el7 will be installed
--> Processing Dependency: perl(Pod::Usage) >= 1.14 for package: perl-Getopt-Long-2.40-3.el7.noarch
--> Processing Dependency: perl(Text::ParseWords) for package: perl-Getopt-Long-2.40-3.el7.noarch
---> Package perl-PathTools.x86_64 0:3.40-5.el7 will be installed
---> Package perl-Pod-Simple.noarch 1:3.28-4.el7 will be installed
--> Processing Dependency: perl(Pod::Escapes) >= 1.04 for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
--> Processing Dependency: perl(Encode) for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
---> Package perl-Scalar-List-Utils.x86_64 0:1.27-248.el7 will be installed
---> Package perl-Socket.x86_64 0:2.010-4.el7 will be installed
---> Package perl-Storable.x86_64 0:2.45-3.el7 will be installed
---> Package perl-Time-HiRes.x86_64 4:1.9725-3.el7 will be installed
---> Package perl-Time-Local.noarch 0:1.2300-2.el7 will be installed
---> Package perl-macros.x86_64 4:5.16.3-294.el7_6 will be installed
---> Package perl-threads.x86_64 0:1.87-4.el7 will be installed
---> Package perl-threads-shared.x86_64 0:1.43-6.el7 will be installed
--> Running transaction check
---> Package dejavu-sans-fonts.noarch 0:2.33-6.el7 will be installed
--> Processing Dependency: dejavu-fonts-common = 2.33-6.el7 for package: dejavu-sans-fonts-2.33-6.el7.noarch
---> Package fontpackages-filesystem.noarch 0:1.44-8.el7 will be installed
---> Package libX11-common.noarch 0:1.6.5-2.el7 will be installed
---> Package libxcb.x86_64 0:1.13-1.el7 will be installed
--> Processing Dependency: libXau.so.6()(64bit) for package: libxcb-1.13-1.el7.x86_64
---> Package perl-Encode.x86_64 0:2.51-7.el7 will be installed
---> Package perl-Pod-Escapes.noarch 1:1.04-294.el7_6 will be installed
---> Package perl-Pod-Usage.noarch 0:1.63-3.el7 will be installed
--> Processing Dependency: perl(Pod::Text) >= 3.15 for package: perl-Pod-Usage-1.63-3.el7.noarch
--> Processing Dependency: perl-Pod-Perldoc for package: perl-Pod-Usage-1.63-3.el7.noarch
---> Package perl-Text-ParseWords.noarch 0:3.29-4.el7 will be installed
--> Running transaction check
---> Package dejavu-fonts-common.noarch 0:2.33-6.el7 will be installed
---> Package libXau.x86_64 0:1.0.8-2.1.el7 will be installed
---> Package perl-Pod-Perldoc.noarch 0:3.20-4.el7 will be installed
--> Processing Dependency: perl(parent) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: perl(HTTP::Tiny) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: groff-base for package: perl-Pod-Perldoc-3.20-4.el7.noarch
---> Package perl-podlators.noarch 0:2.5.1-3.el7 will be installed
--> Running transaction check
---> Package groff-base.x86_64 0:1.22.2-8.el7 will be installed
---> Package perl-HTTP-Tiny.noarch 0:0.033-3.el7 will be installed
---> Package perl-parent.noarch 1:0.225-244.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                       Arch     Version                 Repository
                                                                           Size
================================================================================
Installing:
 nginx                         x86_64   1:1.12.2-2.el7          epel      530 k
Installing for dependencies:
 GeoIP                         x86_64   1.5.0-13.el7            base      1.5 M
 dejavu-fonts-common           noarch   2.33-6.el7              base       64 k
 dejavu-sans-fonts             noarch   2.33-6.el7              base      1.4 M
 fontconfig                    x86_64   2.13.0-4.3.el7          base      254 k
 fontpackages-filesystem       noarch   1.44-8.el7              base      9.9 k
 freetype                      x86_64   2.8-12.el7_6.1          updates   380 k
 gd                            x86_64   2.0.35-26.el7           base      146 k
 gperftools-libs               x86_64   2.6.1-1.el7             base      272 k
 groff-base                    x86_64   1.22.2-8.el7            base      942 k
 libX11                        x86_64   1.6.5-2.el7             base      606 k
 libX11-common                 noarch   1.6.5-2.el7             base      164 k
 libXau                        x86_64   1.0.8-2.1.el7           base       29 k
 libXpm                        x86_64   3.5.12-1.el7            base       55 k
 libjpeg-turbo                 x86_64   1.2.90-6.el7            base      134 k
 libpng                        x86_64   2:1.5.13-7.el7_2        base      213 k
 libxcb                        x86_64   1.13-1.el7              base      214 k
 libxslt                       x86_64   1.1.28-5.el7            base      242 k
 make                          x86_64   1:3.82-23.el7           base      420 k
 nginx-all-modules             noarch   1:1.12.2-2.el7          epel       16 k
 nginx-filesystem              noarch   1:1.12.2-2.el7          epel       17 k
 nginx-mod-http-geoip          x86_64   1:1.12.2-2.el7          epel       23 k
 nginx-mod-http-image-filter   x86_64   1:1.12.2-2.el7          epel       26 k
 nginx-mod-http-perl           x86_64   1:1.12.2-2.el7          epel       36 k
 nginx-mod-http-xslt-filter    x86_64   1:1.12.2-2.el7          epel       26 k
 nginx-mod-mail                x86_64   1:1.12.2-2.el7          epel       54 k
 nginx-mod-stream              x86_64   1:1.12.2-2.el7          epel       76 k
 openssl                       x86_64   1:1.0.2k-16.el7_6.1     updates   493 k
 perl                          x86_64   4:5.16.3-294.el7_6      updates   8.0 M
 perl-Carp                     noarch   1.26-244.el7            base       19 k
 perl-Encode                   x86_64   2.51-7.el7              base      1.5 M
 perl-Exporter                 noarch   5.68-3.el7              base       28 k
 perl-File-Path                noarch   2.09-2.el7              base       26 k
 perl-File-Temp                noarch   0.23.01-3.el7           base       56 k
 perl-Filter                   x86_64   1.49-3.el7              base       76 k
 perl-Getopt-Long              noarch   2.40-3.el7              base       56 k
 perl-HTTP-Tiny                noarch   0.033-3.el7             base       38 k
 perl-PathTools                x86_64   3.40-5.el7              base       82 k
 perl-Pod-Escapes              noarch   1:1.04-294.el7_6        updates    51 k
 perl-Pod-Perldoc              noarch   3.20-4.el7              base       87 k
 perl-Pod-Simple               noarch   1:3.28-4.el7            base      216 k
 perl-Pod-Usage                noarch   1.63-3.el7              base       27 k
 perl-Scalar-List-Utils        x86_64   1.27-248.el7            base       36 k
 perl-Socket                   x86_64   2.010-4.el7             base       49 k
 perl-Storable                 x86_64   2.45-3.el7              base       77 k
 perl-Text-ParseWords          noarch   3.29-4.el7              base       14 k
 perl-Time-HiRes               x86_64   4:1.9725-3.el7          base       45 k
 perl-Time-Local               noarch   1.2300-2.el7            base       24 k
 perl-constant                 noarch   1.27-2.el7              base       19 k
 perl-libs                     x86_64   4:5.16.3-294.el7_6      updates   688 k
 perl-macros                   x86_64   4:5.16.3-294.el7_6      updates    44 k
 perl-parent                   noarch   1:0.225-244.el7         base       12 k
 perl-podlators                noarch   2.5.1-3.el7             base      112 k
 perl-threads                  x86_64   1.87-4.el7              base       49 k
 perl-threads-shared           x86_64   1.43-6.el7              base       39 k
Updating for dependencies:
 openssl-libs                  x86_64   1:1.0.2k-16.el7_6.1     updates   1.2 M

Transaction Summary
================================================================================
Install  1 Package  (+54 Dependent packages)
Upgrade             (  1 Dependent package)

Total download size: 21 M
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
warning: /var/cache/yum/x86_64/7/base/packages/fontpackages-filesystem-1.44-8.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Public key for fontpackages-filesystem-1.44-8.el7.noarch.rpm is not installed
Public key for freetype-2.8-12.el7_6.1.x86_64.rpm is not installed
warning: /var/cache/yum/x86_64/7/epel/packages/nginx-all-modules-1.12.2-2.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY
Public key for nginx-all-modules-1.12.2-2.el7.noarch.rpm is not installed
--------------------------------------------------------------------------------
Total                                              608 kB/s |  21 MB  00:35     
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Importing GPG key 0xF4A80EB5:
 Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>"
 Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
 Package    : centos-release-7-6.1810.2.el7.centos.x86_64 (@CentOS)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Importing GPG key 0x352C64E5:
 Userid     : "Fedora EPEL (7) <epel@fedoraproject.org>"
 Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5
 Package    : epel-release-7-11.noarch (installed)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Warning: RPMDB altered outside of yum.
  Updating   : 1:openssl-libs-1.0.2k-16.el7_6.1.x86_64                     1/57 
  Installing : fontpackages-filesystem-1.44-8.el7.noarch                   2/57 
  Installing : 2:libpng-1.5.13-7.el7_2.x86_64                              3/57 
  Installing : freetype-2.8-12.el7_6.1.x86_64                              4/57 
  Installing : dejavu-fonts-common-2.33-6.el7.noarch                       5/57 
  Installing : dejavu-sans-fonts-2.33-6.el7.noarch                         6/57 
  Installing : fontconfig-2.13.0-4.3.el7.x86_64                            7/57 
  Installing : 1:make-3.82-23.el7.x86_64                                   8/57 
  Installing : 1:openssl-1.0.2k-16.el7_6.1.x86_64                          9/57 
  Installing : libX11-common-1.6.5-2.el7.noarch                           10/57 
  Installing : gperftools-libs-2.6.1-1.el7.x86_64                         11/57 
  Installing : libXau-1.0.8-2.1.el7.x86_64                                12/57 
  Installing : libxcb-1.13-1.el7.x86_64                                   13/57 
  Installing : libX11-1.6.5-2.el7.x86_64                                  14/57 
  Installing : libXpm-3.5.12-1.el7.x86_64                                 15/57 
  Installing : libxslt-1.1.28-5.el7.x86_64                                16/57 
  Installing : 1:nginx-filesystem-1.12.2-2.el7.noarch                     17/57 
  Installing : GeoIP-1.5.0-13.el7.x86_64                                  18/57 
  Installing : libjpeg-turbo-1.2.90-6.el7.x86_64                          19/57 
  Installing : gd-2.0.35-26.el7.x86_64                                    20/57 
  Installing : groff-base-1.22.2-8.el7.x86_64                             21/57 
  Installing : 1:perl-parent-0.225-244.el7.noarch                         22/57 
  Installing : perl-HTTP-Tiny-0.033-3.el7.noarch                          23/57 
  Installing : perl-podlators-2.5.1-3.el7.noarch                          24/57 
  Installing : perl-Pod-Perldoc-3.20-4.el7.noarch                         25/57 
  Installing : perl-Encode-2.51-7.el7.x86_64                              26/57 
  Installing : perl-Text-ParseWords-3.29-4.el7.noarch                     27/57 
  Installing : 1:perl-Pod-Escapes-1.04-294.el7_6.noarch                   28/57 
  Installing : perl-Pod-Usage-1.63-3.el7.noarch                           29/57 
  Installing : 4:perl-libs-5.16.3-294.el7_6.x86_64                        30/57 
  Installing : 4:perl-macros-5.16.3-294.el7_6.x86_64                      31/57 
  Installing : 4:perl-Time-HiRes-1.9725-3.el7.x86_64                      32/57 
  Installing : perl-Exporter-5.68-3.el7.noarch                            33/57 
  Installing : perl-constant-1.27-2.el7.noarch                            34/57 
  Installing : perl-Time-Local-1.2300-2.el7.noarch                        35/57 
  Installing : perl-Carp-1.26-244.el7.noarch                              36/57 
  Installing : perl-Storable-2.45-3.el7.x86_64                            37/57 
  Installing : perl-PathTools-3.40-5.el7.x86_64                           38/57 
  Installing : perl-Scalar-List-Utils-1.27-248.el7.x86_64                 39/57 
  Installing : 1:perl-Pod-Simple-3.28-4.el7.noarch                        40/57 
  Installing : perl-File-Temp-0.23.01-3.el7.noarch                        41/57 
  Installing : perl-File-Path-2.09-2.el7.noarch                           42/57 
  Installing : perl-threads-shared-1.43-6.el7.x86_64                      43/57 
  Installing : perl-threads-1.87-4.el7.x86_64                             44/57 
  Installing : perl-Filter-1.49-3.el7.x86_64                              45/57 
  Installing : perl-Socket-2.010-4.el7.x86_64                             46/57 
  Installing : perl-Getopt-Long-2.40-3.el7.noarch                         47/57 
  Installing : 4:perl-5.16.3-294.el7_6.x86_64                             48/57 
  Installing : 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64           49/57 
  Installing : 1:nginx-mod-http-geoip-1.12.2-2.el7.x86_64                 50/57 
  Installing : 1:nginx-mod-stream-1.12.2-2.el7.x86_64                     51/57 
  Installing : 1:nginx-mod-mail-1.12.2-2.el7.x86_64                       52/57 
  Installing : 1:nginx-mod-http-image-filter-1.12.2-2.el7.x86_64          53/57 
  Installing : 1:nginx-1.12.2-2.el7.x86_64                                54/57 
  Installing : 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64                  55/57 
  Installing : 1:nginx-all-modules-1.12.2-2.el7.noarch                    56/57 
  Cleanup    : 1:openssl-libs-1.0.2k-16.el7.x86_64                        57/57 
  Verifying  : perl-HTTP-Tiny-0.033-3.el7.noarch                           1/57 
  Verifying  : fontconfig-2.13.0-4.3.el7.x86_64                            2/57 
  Verifying  : 1:nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64            3/57 
  Verifying  : perl-threads-shared-1.43-6.el7.x86_64                       4/57 
  Verifying  : 4:perl-Time-HiRes-1.9725-3.el7.x86_64                       5/57 
  Verifying  : 1:nginx-mod-http-geoip-1.12.2-2.el7.x86_64                  6/57 
  Verifying  : groff-base-1.22.2-8.el7.x86_64                              7/57 
  Verifying  : perl-Exporter-5.68-3.el7.noarch                             8/57 
  Verifying  : perl-constant-1.27-2.el7.noarch                             9/57 
  Verifying  : perl-PathTools-3.40-5.el7.x86_64                           10/57 
  Verifying  : 2:libpng-1.5.13-7.el7_2.x86_64                             11/57 
  Verifying  : dejavu-fonts-common-2.33-6.el7.noarch                      12/57 
  Verifying  : fontpackages-filesystem-1.44-8.el7.noarch                  13/57 
  Verifying  : 1:nginx-mod-stream-1.12.2-2.el7.x86_64                     14/57 
  Verifying  : libjpeg-turbo-1.2.90-6.el7.x86_64                          15/57 
  Verifying  : 1:perl-parent-0.225-244.el7.noarch                         16/57 
  Verifying  : GeoIP-1.5.0-13.el7.x86_64                                  17/57 
  Verifying  : 4:perl-libs-5.16.3-294.el7_6.x86_64                        18/57 
  Verifying  : perl-Encode-2.51-7.el7.x86_64                              19/57 
  Verifying  : perl-File-Temp-0.23.01-3.el7.noarch                        20/57 
  Verifying  : 1:perl-Pod-Simple-3.28-4.el7.noarch                        21/57 
  Verifying  : perl-Getopt-Long-2.40-3.el7.noarch                         22/57 
  Verifying  : 1:nginx-all-modules-1.12.2-2.el7.noarch                    23/57 
  Verifying  : libxcb-1.13-1.el7.x86_64                                   24/57 
  Verifying  : perl-Time-Local-1.2300-2.el7.noarch                        25/57 
  Verifying  : 4:perl-macros-5.16.3-294.el7_6.x86_64                      26/57 
  Verifying  : 4:perl-5.16.3-294.el7_6.x86_64                             27/57 
  Verifying  : libXpm-3.5.12-1.el7.x86_64                                 28/57 
  Verifying  : perl-Text-ParseWords-3.29-4.el7.noarch                     29/57 
  Verifying  : 1:openssl-1.0.2k-16.el7_6.1.x86_64                         30/57 
  Verifying  : 1:nginx-filesystem-1.12.2-2.el7.noarch                     31/57 
  Verifying  : perl-Carp-1.26-244.el7.noarch                              32/57 
  Verifying  : libxslt-1.1.28-5.el7.x86_64                                33/57 
  Verifying  : libX11-1.6.5-2.el7.x86_64                                  34/57 
  Verifying  : perl-Storable-2.45-3.el7.x86_64                            35/57 
  Verifying  : dejavu-sans-fonts-2.33-6.el7.noarch                        36/57 
  Verifying  : 1:nginx-mod-mail-1.12.2-2.el7.x86_64                       37/57 
  Verifying  : perl-Scalar-List-Utils-1.27-248.el7.x86_64                 38/57 
  Verifying  : gd-2.0.35-26.el7.x86_64                                    39/57 
  Verifying  : 1:perl-Pod-Escapes-1.04-294.el7_6.noarch                   40/57 
  Verifying  : 1:nginx-mod-http-image-filter-1.12.2-2.el7.x86_64          41/57 
  Verifying  : perl-Pod-Usage-1.63-3.el7.noarch                           42/57 
  Verifying  : 1:openssl-libs-1.0.2k-16.el7_6.1.x86_64                    43/57 
  Verifying  : 1:nginx-1.12.2-2.el7.x86_64                                44/57 
  Verifying  : perl-Pod-Perldoc-3.20-4.el7.noarch                         45/57 
  Verifying  : perl-podlators-2.5.1-3.el7.noarch                          46/57 
  Verifying  : libXau-1.0.8-2.1.el7.x86_64                                47/57 
  Verifying  : perl-File-Path-2.09-2.el7.noarch                           48/57 
  Verifying  : perl-threads-1.87-4.el7.x86_64                             49/57 
  Verifying  : gperftools-libs-2.6.1-1.el7.x86_64                         50/57 
  Verifying  : libX11-common-1.6.5-2.el7.noarch                           51/57 
  Verifying  : perl-Filter-1.49-3.el7.x86_64                              52/57 
  Verifying  : freetype-2.8-12.el7_6.1.x86_64                             53/57 
  Verifying  : 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64                  54/57 
  Verifying  : perl-Socket-2.010-4.el7.x86_64                             55/57 
  Verifying  : 1:make-3.82-23.el7.x86_64                                  56/57 
  Verifying  : 1:openssl-libs-1.0.2k-16.el7.x86_64                        57/57 

Installed:
  nginx.x86_64 1:1.12.2-2.el7                                                   

Dependency Installed:
  GeoIP.x86_64 0:1.5.0-13.el7                                                   
  dejavu-fonts-common.noarch 0:2.33-6.el7                                       
  dejavu-sans-fonts.noarch 0:2.33-6.el7                                         
  fontconfig.x86_64 0:2.13.0-4.3.el7                                            
  fontpackages-filesystem.noarch 0:1.44-8.el7                                   
  freetype.x86_64 0:2.8-12.el7_6.1                                              
  gd.x86_64 0:2.0.35-26.el7                                                     
  gperftools-libs.x86_64 0:2.6.1-1.el7                                          
  groff-base.x86_64 0:1.22.2-8.el7                                              
  libX11.x86_64 0:1.6.5-2.el7                                                   
  libX11-common.noarch 0:1.6.5-2.el7                                            
  libXau.x86_64 0:1.0.8-2.1.el7                                                 
  libXpm.x86_64 0:3.5.12-1.el7                                                  
  libjpeg-turbo.x86_64 0:1.2.90-6.el7                                           
  libpng.x86_64 2:1.5.13-7.el7_2                                                
  libxcb.x86_64 0:1.13-1.el7                                                    
  libxslt.x86_64 0:1.1.28-5.el7                                                 
  make.x86_64 1:3.82-23.el7                                                     
  nginx-all-modules.noarch 1:1.12.2-2.el7                                       
  nginx-filesystem.noarch 1:1.12.2-2.el7                                        
  nginx-mod-http-geoip.x86_64 1:1.12.2-2.el7                                    
  nginx-mod-http-image-filter.x86_64 1:1.12.2-2.el7                             
  nginx-mod-http-perl.x86_64 1:1.12.2-2.el7                                     
  nginx-mod-http-xslt-filter.x86_64 1:1.12.2-2.el7                              
  nginx-mod-mail.x86_64 1:1.12.2-2.el7                                          
  nginx-mod-stream.x86_64 1:1.12.2-2.el7                                        
  openssl.x86_64 1:1.0.2k-16.el7_6.1                                            
  perl.x86_64 4:5.16.3-294.el7_6                                                
  perl-Carp.noarch 0:1.26-244.el7                                               
  perl-Encode.x86_64 0:2.51-7.el7                                               
  perl-Exporter.noarch 0:5.68-3.el7                                             
  perl-File-Path.noarch 0:2.09-2.el7                                            
  perl-File-Temp.noarch 0:0.23.01-3.el7                                         
  perl-Filter.x86_64 0:1.49-3.el7                                               
  perl-Getopt-Long.noarch 0:2.40-3.el7                                          
  perl-HTTP-Tiny.noarch 0:0.033-3.el7                                           
  perl-PathTools.x86_64 0:3.40-5.el7                                            
  perl-Pod-Escapes.noarch 1:1.04-294.el7_6                                      
  perl-Pod-Perldoc.noarch 0:3.20-4.el7                                          
  perl-Pod-Simple.noarch 1:3.28-4.el7                                           
  perl-Pod-Usage.noarch 0:1.63-3.el7                                            
  perl-Scalar-List-Utils.x86_64 0:1.27-248.el7                                  
  perl-Socket.x86_64 0:2.010-4.el7                                              
  perl-Storable.x86_64 0:2.45-3.el7                                             
  perl-Text-ParseWords.noarch 0:3.29-4.el7                                      
  perl-Time-HiRes.x86_64 4:1.9725-3.el7                                         
  perl-Time-Local.noarch 0:1.2300-2.el7                                         
  perl-constant.noarch 0:1.27-2.el7                                             
  perl-libs.x86_64 4:5.16.3-294.el7_6                                           
  perl-macros.x86_64 4:5.16.3-294.el7_6                                         
  perl-parent.noarch 1:0.225-244.el7                                            
  perl-podlators.noarch 0:2.5.1-3.el7                                           
  perl-threads.x86_64 0:1.87-4.el7                                              
  perl-threads-shared.x86_64 0:1.43-6.el7                                       

Dependency Updated:
  openssl-libs.x86_64 1:1.0.2k-16.el7_6.1                                       

Complete!
Loaded plugins: fastestmirror, ovl
Cleaning repos: base epel extras updates
Cleaning up list of fastest mirrors
Removing intermediate container 3e228aab6696
 ---> d31beb8cce1e
Step 5/8 : RUN echo "daemon off;" >> /etc/nginx/nginx.conf
 ---> Running in e2770ee72af0
Removing intermediate container e2770ee72af0
 ---> 56382e656884
Step 6/8 : ADD index.html /usr/share/nginx/html/index.html
 ---> 9a268246ca18
Step 7/8 : EXPOSE 80
 ---> Running in 92412b2bb046
Removing intermediate container 92412b2bb046
 ---> 05ce68ba1519
Step 8/8 : CMD ["nginx"]
 ---> Running in fa9037b49675
Removing intermediate container fa9037b49675
 ---> 5aee9f4c1ada
Successfully built 5aee9f4c1ada
Successfully tagged mynginx:v2
[root@localhost nginx]# docker image

Usage:    docker image COMMAND

Manage images

Commands:
  build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

Run 'docker image COMMAND --help' for more information on a command.
[root@localhost nginx]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mynginx             v2                  5aee9f4c1ada        14 seconds ago      307MB
centos              latest              9f38484d220f        10 days ago         202MB
nginx               latest              881bd08c0b08        2 weeks ago         109MB
[root@localhost nginx]# 
docker build -t mynginx:v2 .

 启动镜像

[root@localhost nginx]# cat index.html 
<html>
<body>
<h1>首页!!!!</h1>
</body>
</html>
[root@localhost nginx]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mynginx             v2                  5aee9f4c1ada        4 minutes ago       307MB
centos              latest              9f38484d220f        10 days ago         202MB
nginx               latest              881bd08c0b08        2 weeks ago         109MB
[root@localhost nginx]# docker run --name mynginxv2 -d -p 81:80 mynginx:v2 nginx
8e269403c1b4181dd187eb20c74eb465f5f165ce0bfbc9b444d57164b1621e24
[root@localhost nginx]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
8e269403c1b4        mynginx:v2          "nginx"             4 seconds ago       Up 3 seconds        0.0.0.0:81->80/tcp   mynginxv2
[root@localhost nginx]# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:86:32:27 brd ff:ff:ff:ff:ff:ff
    inet 192.168.226.159/24 brd 192.168.226.255 scope global dynamic ens33
       valid_lft 1636sec preferred_lft 1636sec
    inet6 fe80::6f1c:2b48:af8b:a03a/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
    link/ether 52:54:00:31:bf:a8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
    link/ether 52:54:00:31:bf:a8 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:b4:4c:77:45 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:b4ff:fe4c:7745/64 scope link 
       valid_lft forever preferred_lft forever
79: veth3778ee4@if78: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether d2:b8:51:47:0d:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::d0b8:51ff:fe47:d1d/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost nginx]# curl 192.168.226.159:81
<html>
<body>
<h1>首页!!!!</h1>
</body>
</html>
[root@localhost nginx]# 

 docker run --name mynginxv2 -d -p 81:80 mynginx:v2 nginx
docker run --name mynginxv2 -d -p 81:80 mynginx:v2 nginx

 

构建Uwsgi+Python开发环境

FROM python:3.7.6 AS pure_python_env
MAINTAINER franplk
LABEL version=1.0 description=HunanModelSystem

FROM pure_python_env AS python_site_package
WORKDIR /root
COPY requirements.txt  requirements.txt
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple


FROM python_site_package AS uwsgi_builder
WORKDIR /root
COPY uwsgi/uwsgi-2.0.19.1 uwsgi-2.0.19.1
RUN mv uwsgi-2.0.19.1 uwsgi
WORKDIR /root/uwsgi
RUN make && ln -s /root/uwsgi/uwsgi /usr/bin/uwsgi
EXPOSE 8099
WORKDIR /root
CMD uwsgi --ini /${PROJECT_NAME}/devops/docker/uwsgi/uwsgi.ini

 

CMD执行

CMD用来设置docker run 容器启动之后,执行的命令。它通常是在操作系统前台启动1个进程。

注意一定要保证docker容器内有1个前台进行一直运行,否则容器会马上退出。Dockerfile中启动服务不需要nohup。

#!/bin/bash
#load variables from uwsgi.ini  
projectConfig=$(grep ^chdir= /root/uwsgi.ini)
projectPath=$(echo | awk '{split("'${projectConfig}'", array, "=");print array[2]}')
projectName=$(echo | awk '{split("'${projectPath}'", array, "/");print array[5]}')

#Create a directory to store cureent project
cd /usr/src/app/
mv /root/code/${projectName} /usr/src/app/
echo $projectName is being started by Docker.

#Launch the project with python
#cd $projectPath
#python manager.py

#Launch the project with uwsgi
uwsgi --ini /root/uwsgi.ini
run.sh

uwsgi配置文件

wsgi]
master=true
processes=8
http=0.0.0.0:8099
module=manager
callable=app
buffer-size=65535
chmod-socket=777
logfile-chmod=644
# 源码目录
chdir=/usr/src/app/HunanModel/code
# python 虚拟环境
socket=/root/app/uwsgi.sock
pidfile=/root/app/uwsgi.pid
#如果在docker容纳其里,一定让uwsgi在前台启动
#daemonize=/root/app/uwsgi.log
                                 
uwsgi.ini

build镜像

./docker/docker build  -t modelsystem:2.0 . 

run容器

[root@localhost mingde]# ./docker/docker run -d -p 8099:8099  --name modelsystem -e PROJECT="HunanModel" modelsystem:2.0
06f162a4301f3174a0a655428e2cbd0c973920190de4bb21e951540121886f04
[root@localhost mingde]# ./docker/docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
06f162a4301f        modelsystem:2.0     "/bin/sh -c 'sh /r..."   7 seconds ago       Up 7 seconds        0.0.0.0:8099->8099/tcp   modelsystem
[root@localhost mingde]# 

让docker容器中的目录挂载到宿主机目录,可以让dockerFile制作的镜像显地更加通用。

也就是说我的docker容器中只是打包了Python环境,而这个Python环境,需要运行的Python代码却是可以随时更的。

[root@localhost mingde]# ./docker/docker run -d -p 8099:8099 -v /mingde:/mingde  --name modelsystem modelsystem:2.0

 

五、docker file生产实践

docker file go live 

1.目录环境准备

[root@localhost docker_image]# ls
apps  runtime  system
[root@localhost docker_image]# tree 
.
├── apps
│   └── work_order_api
├── runtime
│   ├── java
│   ├── php
│   └── python
└── system
    ├── centos
    └── centos-ssh

在架构设计里面有个分层设计的理念,我们也可把生产环境分为:系统层、运行环境层、业务层,这也符合docker镜像分层思想;

Linux系统: centos、Ubuntu....

运行环境: Java 、Python 、PHP.....

App:API、WebAPP、BackGroundManagement ...

Docker file最大的亮点在于FROM,有了它就可以基于不同的镜像,衍生出多种镜像,就和搭积木类似,分好层 可以灵活组装就好。

 

2.系统环境层docker file (centos7)

下载epel.repo源文件

[root@localhost centos]# pwd
/docker_image/system/centos
[root@localhost centos]# wget -O ./epel.repo  http://mirrors.aliyun.com/repo/epel-7.repo
--2019-03-26 09:34:20--  http://mirrors.aliyun.com/repo/epel-7.repo
Resolving mirrors.aliyun.com (mirrors.aliyun.com)... 175.6.29.211, 175.6.29.218, 175.6.29.213, ...
Connecting to mirrors.aliyun.com (mirrors.aliyun.com)|175.6.29.211|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 664 [application/octet-stream]
Saving to: ‘./epel.repo’

100%[==================================================================================================>] 664         --.-K/s   in 0s      

2019-03-26 09:34:20 (138 MB/s) - ‘./epel.repo’ saved [664/664]

[root@localhost centos]# ls
epel.repo
wget -O ./epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
FROM centos
MAINTAINER zhanggen
ADD epel.repo /etc/yum.repos.d/
run yum install -y wget mysql-devel supervisor git redis tree net-toos sudo psmisc && yum clean all
Dockerfile
[root@localhost centos]# ls
Dockerfile  epel.repo
[root@localhost centos]# docker build -t zhanggen/centos:v1 .
docker build -t zhanggen/centos:v1 .

 

3.开发环境层docker file (Python3.6.1)

[root@localhost python]# pwd
/docker_image/runtime/python
[root@localhost python]# ls
Dockerfile  Python-3.6.1.tgz
[root@localhost python]# 
FROM zhanggen/centos:v1

MAINTAINER Gen.Zhang

RUN yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel gcc automake autoconf libtool make db4-devel libpcap-devel xz-devel

RUN yum clean all

ADD Python-3.6.1.tgz /python_packages/

RUN mkdir -p /zhanggen/python3.6.1

RUN cd /python_packages/Python-3.6.1 && ./configure --prefix=/zhanggen/python3.6.1 && make && make install

RUN echo -e "PATH=$PATH:$HOME/bin:/zhanggen/python3.6.1/bin \n export PATH" > /etc/profile.d/python3.6.1.sh && source /etc/profile.d/python3.6.1.sh
Dockerfile

 构建python开发环境镜像

[root@localhost runtime]# cd python/
[root@localhost python]# ls
Dockerfile  Python-3.6.1.tgz
[root@localhost python]# docker build -t zhanggen/python3.6.1:v1 .
Sending build context to Docker daemon  22.54MB
Step 1/8 : FROM zhanggen/centos:v1
 ---> 9c10a3b17a66
Step 2/8 : MAINTAINER Gen.Zhang
 ---> Using cache
 ---> 4c630636d1f9
Step 3/8 : RUN yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel gcc automake autoconf libtool make db4-devel libpcap-devel xz-devel
 ---> Using cache
 ---> ff12b7d7dbd3
Step 4/8 : RUN yum clean all
 ---> Using cache
 ---> 32c615445b0a
Step 5/8 : ADD Python-3.6.1.tgz /python_packages/
 ---> Using cache
 ---> ac70242e584b
Step 6/8 : RUN mkdir -p /zhanggen/python3.6.1
 ---> Using cache
 ---> 426627a6cb1f
Step 7/8 : RUN cd /python_packages/Python-3.6.1 && ./configure --prefix=/zhanggen/python3.6.1 && make && make install
 ---> Using cache
 ---> d15daa242a06
Step 8/8 : RUN echo -e "PATH=$PATH:$HOME/bin:/zhanggen/python3.6.1/bin \n export PATH" > /etc/profile.d/python3.6.1.sh && source /etc/profile.d/python3.6.1.sh
 ---> Using cache
 ---> 20e32f2fde08
Successfully built 20e32f2fde08
Successfully tagged zhanggen/python3.6.1:v1
[root@localhost python]# docker build -t zhanggen/python3.6.1:v1 .
Sending build context to Docker daemon  22.54MB
Step 1/8 : FROM zhanggen/centos:v1
 ---> 9c10a3b17a66
Step 2/8 : MAINTAINER Gen.Zhang
 ---> Using cache
 ---> 4c630636d1f9
Step 3/8 : RUN yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel gcc automake autoconf libtool make db4-devel libpcap-devel xz-devel
 ---> Using cache
 ---> ff12b7d7dbd3
Step 4/8 : RUN yum clean all
 ---> Using cache
 ---> 32c615445b0a
Step 5/8 : ADD Python-3.6.1.tgz /python_packages/
 ---> Using cache
 ---> ac70242e584b
Step 6/8 : RUN mkdir -p /zhanggen/python3.6.1
 ---> Using cache
 ---> 426627a6cb1f
Step 7/8 : RUN cd /python_packages/Python-3.6.1 && ./configure --prefix=/zhanggen/python3.6.1 && make && make install
 ---> Using cache
 ---> d15daa242a06
Step 8/8 : RUN echo -e "PATH=$PATH:$HOME/bin:/zhanggen/python3.6.1/bin \n export PATH" > /etc/profile.d/python3.6.1.sh && source /etc/profile.d/python3.6.1.sh
 ---> Using cache
 ---> 20e32f2fde08
Successfully built 20e32f2fde08
Successfully tagged zhanggen/python3.6.1:v1
[root@localhost python]# pwd
/docker_image/runtime/python
docker build -t zhanggen/python3.6.1:v1 .

 

4.APP层 docker file(Django web app)

Docker容器只允许在前台 运行1个进程,我们如何破解?

Supervisor是Python开发的进程管理工具,可以同时开启、重启、关闭多个进程,可以启动1个Supervisor进程使用Supercisor启动、管理N个进程; 

我发现Supervisor不仅可以统一管理进程,还可以规范进程的日志路径,规范了日志路径之后,就可以很方便得找得这些日志,进行数据分析

[root@localhost web_application]# pwd
/docker_image/apps/web_application
[root@localhost web_application]# ls
django_app  Dockerfile  requirements.txt  supervisord.conf  supervisor.ini
[root@localhost web_application]# 

构建web app镜像所需要的文件

APP项目---自己写

ADD django_app/ /root/django_app/
ADD requirements.txt /root/django_app/

ADD supervisord.conf /etc/supervisord.conf
ADD supervisor.ini  /etc/supervisord.d/
RUN  /zhanggen/python3.6.1/bin/pip3 install -r /root/django_app/requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

EXPOSE 22 8008

CMD ["/usr/bin/supervisord","-c","/etc/supervisord.conf"]
Dockerfile
Django==1.11.4
requirements.txt APP项目需要的 python包
nodaemon=true               ; (start in foreground if true;default false)
supervisord的配置文件 supervisord.conf

配置supervisor需要启动的启动的 程序 

ps:一定记得让supervisord进程 在前台运行(修改配置中件  nodaemon=true)

[program:django_project]
command=/zhanggen/python3.6.1/bin/python3  /root/django_app/manage.py runserver 0.0.0.0:8008
process_name=%(program_name)s
autostart=true
user=root
stdout_logfile=/tmp/app.log
stderr_logfile=/tmp/app.error


[program:sshd]
command=/usr/sbin/sshd -D
process_name=%(program_name)s
autostart=true
user=root
stdout_logfile=/tmp/sshd.log
stderr_logfile=/tmp/sshd.error
supervisor.ini

 构建 web app镜像

Successfully built 73fbd9076308
Successfully tagged zhanggen/django_app:v1
[root@localhost web_application]# pwd
/docker_image/apps/web_application
[root@localhost web_application]# docker build -t zhanggen/django_app:v1 .
docker build -t zhanggen/django_app:v1 .

启动web app

[root@localhost web_application]# docker run --name my_django_app -d -p 8008:8008 -p 8022:22 zhanggen/django_app:v1 
185c311d6a951e33fa01d64a332127cf9ad6d45b0ee60d018ab25be68c0a86bf
[root@localhost web_application]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                          NAMES
185c311d6a95        zhanggen/django_app:v1   "/usr/bin/supervisor…"   7 seconds ago       Up 5 seconds        0.0.0.0:8008->8008/tcp, 0.0.0.0:8022->22/tcp   my_django_app
[root@localhost web_application]# 
docker run --name my_django_app -d -p 8008:8008 -p 8022:22 zhanggen/django_app:v1

 最后的最后

[root@localhost web_application]# docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
zhanggen/django_app    v1                  a25dd5479dd9        8 minutes ago       905MB
zhanggen/python3.6.1   v1                  20e32f2fde08        19 hours ago        882MB
zhanggen/centos        v1                  9c10a3b17a66        20 hours ago        300MB
[root@localhost web_application]# docker run --name my_django_app -d -p 8008:8008 -p 8022:22 zhanggen/django_app:v1 
最终构建的3个镜像

5.Dockerfile中cmd和entrypoint指令联系和区别

每1个Dockerfile只能生效1条CMD指令。如果指定了多条CMD指令,只有最后1条生效

如果用户启动容器(docker run image)时候指定了运行的命令,则会覆盖掉CMD指定的命令

每1个Dockerfile中只能生效一个ENTRYPOINT指令,当有多个ENTRYPOINT指令时,只有最后1条生效。

如果用户启动容器(docker run image)时指定了运行的命令,不会被docker run输入命令参数覆盖。(追加效果:docker run命令之后的参数,会被当做参数传递给ENTRYPOINT,之后形成新的命令组合)

六、Docker仓库(Docker Registry)

docker镜像做好了,这些镜像怎么分享给其他同事,其他同事的镜像 How to share with me?

于是私有Docker Hub-----Harbor闪亮登场了!

我们可以把这些镜像 push  / pull 到Docker仓库里面,通过Docker仓库 使镜像 得以分享、传播;

 

 

 1.Harbor私有仓库搭建

 

2.Docker 添加--insecure-registry信任关系

ExecStart=/usr/bin/dockerd --insecure-registry=192.168.226.159:80
vim /usr/lib/systemd/system/docker.service

 

3.首次使用Harbor需要先登录做一下认证 (Authenticating)

[root@localhost /]# docker login 192.168.226.159:80
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/#credentials-store

Login Succeeded
docker login 192.168.226.159:80

 

4.在提交到Harbor之前 要先对本地镜像进行 docker tag

[root@localhost /]# docker tag 192.168.226.159/zhanggen/django_app:v1 192.168.226.159:80/zhanggen/django_app:v1
[root@localhost /]# docker push 192.168.226.159:80/zhanggen/django_app:v1
The push refers to repository [192.168.226.159:80/zhanggen/django_app]
1adfc5932576: Pushed 
f35015fe99dc: Pushed 
130d88c10146: Pushed 
af1537967ae6: Pushed 
8bc7239a5750: Pushed 
4044728999b8: Pushed 
7393a01b80a0: Pushed 
8682a21900da: Pushed 
4b12cdc82a32: Pushed 
325cddbb1805: Pushed 
5e3f3498e333: Pushed 
9b0549f1a2e2: Pushed 
5d14ce4c4502: Pushed 
d7180aa9852e: Pushed 
d69483a6face: Mounted from zhanggen/mycentos 
v1: digest: sha256:9b4aaeb6d37466a92d3705b68b20c5bf27db1a21ef75456dd2433822b0bf5b60 size: 3457
docker tag 192.168.226.159/zhanggen/django_app:v1 192.168.226.159:80/zhanggen/django_app:v1

 

 5.docker push ---->Harbor仓库

[root@localhost harbor]# docker login http://192.168.226.159:80
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/#credentials-store

Login Succeeded
[root@localhost harbor]# docker push 192.168.226.159:80/zhanggen/mycentos:v1  
The push refers to repository [192.168.226.159:80/zhanggen/mycentos]
d69483a6face: Pushed 
v1: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@localhost harbor]# 
docker push 192.168.226.159:80/zhanggen/mycentos:v1

 

6.docker pull  本地 <--------Harbor仓库

[root@localhost /]# docker rmi 192.168.226.159:80/zhanggen/mycentos:v1
Untagged: 192.168.226.159:80/zhanggen/mycentos:v1
Untagged: 192.168.226.159:80/zhanggen/mycentos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@localhost /]# docker pull 192.168.226.159:80/zhanggen/mycentos:v1
v1: Pulling from zhanggen/mycentos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for 192.168.226.159:80/zhanggen/mycentos:v1
[root@localhost /]# docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
192.168.226.159/zhanggen/django_app      v1                  a25dd5479dd9        29 hours ago        905MB
192.168.226.159:80/zhanggen/django_app   v1                  a25dd5479dd9        29 hours ago        905MB
zhanggen/django_app                      v1                  a25dd5479dd9        29 hours ago        905MB
zhanggen/python3.6.1                     v1                  20e32f2fde08        2 days ago          882MB
zhanggen/centos                          v1                  9c10a3b17a66        2 days ago          300MB
192.168.226.159/zhanggen/mycentos        v1                  9f38484d220f        13 days ago         202MB
192.168.226.159:80/zhanggen/mycentos     v1                  9f38484d220f        13 days ago         202MB
centos                                   latest              9f38484d220f        13 days ago         202MB
goharbor/chartmuseum-photon              v0.8.1-v1.7.4       7e2272c02339        3 weeks ago         113MB
goharbor/harbor-migrator                 v1.7.4              968c31d07d2f        3 weeks ago         678MB
goharbor/redis-photon                    v1.7.4              611d1ead0a28        3 weeks ago         99.7MB
goharbor/clair-photon                    v2.0.7-v1.7.4       01090529ab14        3 weeks ago         165MB
goharbor/notary-server-photon            v0.6.1-v1.7.4       737518b1b943        3 weeks ago         135MB
goharbor/notary-signer-photon            v0.6.1-v1.7.4       495dc3326120        3 weeks ago         132MB
goharbor/harbor-registryctl              v1.7.4              723aed7bbf8d        3 weeks ago         102MB
goharbor/registry-photon                 v2.6.2-v1.7.4       f4743bd7b0d9        3 weeks ago         86.7MB
goharbor/nginx-photon                    v1.7.4              dda34e6afafe        3 weeks ago         35.9MB
goharbor/harbor-log                      v1.7.4              bf4916eef530        3 weeks ago         81.4MB
goharbor/harbor-jobservice               v1.7.4              1b6a0445ae9c        3 weeks ago         84.1MB
goharbor/harbor-core                     v1.7.4              e603b8750d26        3 weeks ago         95.6MB
goharbor/harbor-portal                   v1.7.4              2ca1d845cafa        3 weeks ago         40.6MB
goharbor/harbor-adminserver              v1.7.4              5706c65d65dc        3 weeks ago         72.3MB
goharbor/harbor-db                       v1.7.4              08d163f732f3        3 weeks ago         136MB
[root@localhost /]# 
docker pull 192.168.226.159:80/zhanggen/mycentos:v1

 

7.Harbor的 后台管理页面

默认登录密码:Harbor12345

8.Harbor之间的镜像数据同步

我们不仅可以使用docker push把本地的镜像推送到Harbor这些镜像仓库。
在2个Harbor镜像仓库直接也可以基于事件/手动进行镜像数据复制和同步。

9.复制规则

设置复制的目录和规则

 

七.docker实践总结

虽然结果只是build了3个镜像,但是我发现docker 的优势在于它可以通过镜像的方式 把Linux系统、开发环境、代码 进行了分层, 我们可以把这些镜像 想象成一个个的积木,有了这些小积木,我们就可以在 实体机、甚至虚拟机里面  灵活、搭建出 各式各样的房子,分给不同需求的人,而且构建速度 快,构建的房子还可以轻易的搬到其他地方;

docker是1种可以 灵活、快速得 构建出 多种不同得 开发、测试 环境的容器技术,Buddy.... 如果你的公司需要构建大量、不同的系统环境用docker 吧!

如果你的代码需要在很多地方快速运行起来用docker吧!

Build-----> Ship---->Run  

1.Python调用Docker的API

介绍1个可用于调用Docker引擎 API 的 Python 库,它允许您执行docker命令所做的任何事情。

可以在 Python 应用程序中执行——打包镜像、管理镜像、运行容器、管理容器、管理 Swarm 等操作。

from public import RecordLoggre
from docker.errors import NotFound
import docker
import os


class DockerApi:

    def __init__(self, harbor_domain, username, password):
        # self.Client = docker.DockerClient(base_url='tcp://127.0.0.1:2375')
        self.Client = docker.from_env()
        self.username = username
        self.password = password
        self.registry_domain = harbor_domain
        self.registry_url = f'https://{self.registry_domain}'
        self.record_log = RecordLoggre()

        login_sigin = 0
        while True:
            try:
                self.Client.login(username=self.username, password=self.password,
                                  registry=self.registry_url)
            except Exception as Error:
                self.record_log.error(str(Error), exc_info=True)
                login_sigin += 1
                if login_sigin >= 3:
                    raise Exception('docker auth error')
            else:
                break

    def build_image(self, work_space, image_url):
        """构建镜像并上传镜像"""
        os.chdir(work_space)
        try:
            build_result = self.Client.images.build(path=work_space, dockerfile='Dockerfile',
                                                    tag=image_url, rm=True, nocache=True,
                                                    forcerm=True, use_config_proxy=True)
        except Exception:
            self.record_log.error('创建镜像失败')
            raise Exception('Build image error!')
        else:
            self.record_log.info('构建镜像成功' + str(build_result))

        self.push_image(image_url)
        self.remove_image(image_url)

    def get_image(self, image_url):
        """获取远端镜像"""
        image_data = None
        try:
            image_data = self.Client.images.get_registry_data(image_url)
        except NotFound:
            self.record_log.warning(f'获取镜像{image_url}失败')
        except Exception as Error:
            self.record_log.error(f'{Error}', exc_info=True)
        return image_data

    def remove_image(self, image_url):
        """删除本地镜像"""
        try:
            self.Client.images.remove(image_url)
        except Exception as Error:
            self.record_log.error(f'{str(Error)}删除本地镜像{image_url}失败')
        else:
            self.record_log.info(f'删除本地镜像{image_url}成功')

    def pull_image(self, image_url):
        """下载镜像"""
        pull_count = 1
        while True:
            try:
                self.Client.images.pull(image_url)
            except Exception as Error:
                self.record_log.error(f'{str(Error)},下载镜像失败,次数{pull_count}', exc_info=True)
                if pull_count >= 3:
                    raise Exception('Pull image error')
            else:
                self.record_log.info('下载镜像成功')
                break
            pull_count += 1

    def push_image(self, image_url):
        """推送镜像"""
        push_count = 1
        while True:
            try:
                self.Client.images.push(image_url)
            except Exception as Error:
                self.record_log.error(f'{str(Error)},推送镜像失败,次数{push_count}', exc_info=True)
                if push_count >= 3:
                    raise Exception('Push image error')
            else:
                self.record_log.info('推送镜像成功')
                break
            push_count += 1

    def rename(self, image_url, repository, tag):
        """更改存存储库"""
        retry_count = 1
        while True:
            try:
                image_obj = self.Client.images.get(image_url)
                image_obj.tag(repository, tag)
            except Exception as Error:
                self.record_log.error(f'{str(Error)},更改存储库失败,次数{retry_count}', exc_info=True)
                if retry_count >= 3:
                    raise Exception('更改存储库失败')
            else:
                self.record_log.info('更改存储库成功')
                break
            retry_count += 1


if __name__ == '__main__':
    pass
DockerAPI.py

2.Python调用Harbor的API

from public import RecordLoggre
from public.DockerApi import DockerApi
from datetime import datetime
import requests


class HarborApi:

    def __init__(self, harbor_domain, username, password):
        self.harbor_domain = harbor_domain
        self.harbor_api = f'https://{harbor_domain}/api/v2.0'
        self.username = username
        self.password = password

        self.req = requests.Session()
        self.req.auth = (self.username, self.password)
        # 记录日志
        self.record_log = RecordLoggre()

    def requests(self, url, method, **kwargs):
        """处理具体请求,获取错误"""
        req_result = {}
        req_func = getattr(self.req, method, 'get')
        try:
            response = req_func(url, **kwargs)
            status_code = response.status_code
        except Exception as Error:
            self.record_log.error(f'{str(Error)},url:{url},method:{method},kwargs:{str(kwargs)}', exc_info=True)
        else:
            if 200 <= status_code < 300:
                if status_code == 204:
                    req_result = response.text
                else:
                    try:
                        req_result = response.json()
                    except Exception:
                        pass
            else:
                self.record_log.error(f'状态码:{status_code},url:{url},返回结果:{str(req_result)},请求参数:{str(kwargs)}')
                req_result = {}
        finally:
            return req_result

    @staticmethod
    def change_repo(repo):
        return repo.replace('/', '%252F')


class HarborApiV233(HarborApi):

    def __init__(self, harbor_domain, username, password):
        super(HarborApiV233, self).__init__(harbor_domain, username, password)

    def list_repos(self, project, repo):
        """列出存储库的所有tags"""
        repo = self.change_repo(repo)
        page, page_size = 1, 20
        while True:
            url = f'{self.harbor_api}/projects/{project}/repositories/{repo}/artifacts'
            req_result = self.requests(url, 'get', params={'page': page, 'page_size': page_size})
            if len(req_result) > 0:
                for item in req_result:
                    yield item
                page += 1
            else:
                break

    def get_tag_list(self, project, repo):
        """获取镜像的tag列表"""
        tags_list = []
        for item in self.list_repos(project, repo):
            for tag in item.get('tags', []):
                name = tag.get('name')
                push_time = tag.get('push_time')
                if name and push_time:
                    tags_list.append((name, datetime.strptime(push_time, '%Y-%m-%dT%H:%M:%S.%fZ').timestamp()))
        sorted_list = sorted(tags_list, key=lambda x: x[1])
        return sorted_list

    def get_repo_list(self, project, repo):
        """获取镜像的artifacts列表"""
        tags_list = []
        for item in self.list_repos(project, repo):
            digest = item.get('digest')
            push_time = item.get('push_time')
            tags_list.append((digest, datetime.strptime(push_time, '%Y-%m-%dT%H:%M:%S.%fZ').timestamp()))
        sorted_list = sorted(tags_list, key=lambda x: x[1])
        return sorted_list

    def tag_exist(self, project, repo, tag):
        """获取单个tag是否存在"""
        repo = self.change_repo(repo)
        url = f'{self.harbor_api}/projects/{project}/repositories/{repo}/artifacts/{tag}/tags'
        req_result = self.requests(url, 'get')
        if len(req_result) == 1:
            return True
        else:
            return False

    def find_last_tag(self, project, repo):
        """获取最新的tag"""
        sorted_list = self.get_tag_list(project, repo)

        if len(sorted_list) == 0:
            raise Exception(f'从{project}/{repo}没找到镜像')
        else:
            return sorted_list[-1]

    def del_repo_tags(self, project, repo, tag):
        """删除对应tag的镜像"""
        repo = self.change_repo(repo)
        url = f'{self.harbor_api}/projects/{project}/repositories/{repo}/artifacts/{tag}'
        self.requests(url, 'delete')

    def clear_image(self, project, repo):
        """清理镜像保留最新10个,接口调不通,使用harbor自带的清理策略"""
        # sorted_list = self.get_repo_list(project, repo)
        # for item in sorted_list[:-10]:
        #     self.del_repo_tags(project, repo, item[0])
        ...


class HarborApiV122(HarborApi):
    """接口文档:https://github.com/goharbor/harbor/blob/release-1.2.0/docs/swagger.yaml"""

    def __init__(self, harbor_domain, username, password):
        super(HarborApiV122, self).__init__(harbor_domain, username, password)

    def get_tag_list(self, project, repo):
        """获取镜像的tag列表"""
        url = f'{self.harbor_api}/repositories/{project}/{repo}/tags'
        req_result = self.requests(url, 'get')
        tags_list = []
        if req_result:
            for item in req_result:
                name = item.get('name')
                push_time = item.get('created')
                if name and push_time:
                    tags_list.append((name, datetime.strptime(push_time[:19], '%Y-%m-%dT%H:%M:%S').timestamp()))
        sorted_list = sorted(tags_list, key=lambda x: x[1])
        return sorted_list

    def tag_exist(self, project, repo, tag):
        """获取单个tag是否存在"""
        url = f'{self.harbor_api}/repositories/{project}/{repo}/tags/{tag}'
        req_result = self.requests(url, 'get')
        return True if req_result else False

    def find_last_tag(self, project, repo):
        """获取最新的tag"""
        sorted_list = self.get_tag_list(project, repo)

        if len(sorted_list) == 0:
            raise Exception(f'从{project}/{repo}没找到镜像')
        else:
            return sorted_list[-1]

    def del_repo_tags(self, project, repo, tag):
        """删除对应tag的镜像"""
        url = f'{self.harbor_api}/repositories/{project}/{repo}/tags/{tag}'
        self.requests(url, 'delete')

    def clear_image(self, project, repo):
        """清理镜像保留最新10个"""
        sorted_list = self.get_tag_list(project, repo)
        for item in sorted_list[:-10]:
            self.del_repo_tags(project, repo, item[0])


def local_harbor():
    """本地镜像仓库"""
    harbor_domain, username, password = 'qa-roc.apuscn.com', 'admin', 'Harbor12345'
    harbor_api = HarborApiV233(harbor_domain, username, password)
    docker_api = DockerApi(harbor_domain, username, password)
    return harbor_api, docker_api


def sg_harbor():
    """新加坡镜像仓库"""
    harbor_domain, username, password = 'roc.apuscn.com', 'admin', 'Harbor12345'
    harbor_api = HarborApiV122(harbor_domain, username, password)
    harbor_api.harbor_api = f'https://{harbor_domain}/api'
    docker_api = DockerApi(harbor_domain, username, password)
    return harbor_api, docker_api


if __name__ == "__main__":
    pass
HarborAPI.py

3.Python调用Minio的API

from public import RecordLoggre
from minio.commonconfig import CopySource
from minio import Minio
from datetime import timedelta
import time
import os


class MinioApi:

    def __init__(self, minio_server, access_key, secret_key, bucket):
        self.minio_client = Minio(
            minio_server,
            access_key=access_key,
            secret_key=secret_key,
            secure=False
        )
        self.bucket = bucket
        self.record_log = RecordLoggre()

    def list_objects(self, prefix):
        """
            获取存储对象
        """
        retry_count, result, object_list = 1, False, None
        while True:
            try:
                objects = self.minio_client.list_objects(self.bucket, prefix=prefix, recursive=True)
            except Exception as error:
                self.record_log.error(error, exc_info=True)
            else:
                if objects:
                    result = True
                    object_list = objects
            finally:
                retry_count += 1
                if result or retry_count > 3:
                    break
        if object_list:
            return object_list
        else:
            raise Exception('获取Minio存储对象失败!')

    def object_exists(self, object_key):
        """检测对象是否存在"""
        object_list = [item for item in self.list_objects(object_key)]
        if object_list:
            return True
        else:
            return False

    def upload_object(self, local_file, object_key):
        """
            上传文件,并检查是否上传成功
        """
        retry_count, result = 1, False
        while True:
            try:
                with open(local_file, 'rb') as file_data:
                    file_stat = os.stat(local_file)
                    etag = self.minio_client.put_object(
                        bucket_name=self.bucket,
                        object_name=object_key,
                        data=file_data,
                        length=file_stat.st_size
                    )

            except Exception as error:
                self.record_log.error(error, exc_info=True)
            else:
                if etag:
                    self.record_log.info('{0} -> {1}/{2} 上传到本地minio对象存储成功'.format(local_file, self.bucket, object_key))
                    result = True
            finally:
                retry_count += 1
                if result or retry_count > 3:
                    break
        return result

    def download_object(self, object_key):
        """下载存储库对象"""
        if self.object_exists(object_key):
            try:
                data = self.minio_client.get_object(
                    bucket_name=self.bucket,
                    object_name=object_key
                )

                file_name = object_key.split('/')[-1]
                with open(file_name, 'wb') as file_data:
                    for d in data.stream(32 * 1024):
                        file_data.write(d)
            except Exception as Error:
                raise Exception(f'下载{object_key}文件出错,{Error}')
        else:
            raise Exception(f'下载{object_key}出错,存储对象不存在')

    def find_last_pack(self, app_path):
        """获取最新的包"""
        object_list = self.list_objects(app_path)
        pack_list = \
            [
                {
                    'upload_date': int(item.object_name.split('/')[-2]),
                    'object_key': item.object_name
                }
                for item in object_list
            ]
        last_pack = sorted(pack_list, key=lambda x: x['upload_date'])[-1]
        return last_pack

    def copy_pack(self, target_key, source_key):
        """拷贝包,对应包晋级动作"""
        copy_result = self.minio_client.copy_object(
            bucket_name=self.bucket,
            object_name=target_key,
            source=CopySource(self.bucket, source_key),
        )
        self.record_log.info(copy_result)

    def del_pack(self, object_key):
        """删除包"""
        try:
            self.minio_client.remove_object(
                bucket_name=self.bucket,
                object_name=object_key
            )
        except Exception as Error:
            self.record_log.error(f'{str(Error)}', exc_info=True)

    def clear_pack(self, object_key):
        """清理包,保留最新10个"""
        object_list = self.list_objects(object_key)
        key_list = []
        for item in object_list:
            key = item.object_name
            last_modified = item.last_modified
            timestamp = time.mktime(last_modified.timetuple())
            key_list.append((key, timestamp))
        sorted_list = sorted(key_list, key=lambda x: x[1])
        for item in sorted_list[:-10]:
            self.del_pack(item[0])

    def get_presigned_url(self, object_name):
        """获取临时下载url,1小时过期"""
        if self.object_exists(object_name):
            down_url = self.minio_client.presigned_get_object(self.bucket, object_name, expires=timedelta(hours=1))
            return down_url
        else:
            raise Exception(f'生成临时下载url失败,{object_name}不存在')


def zz_minio():
    """郑州本地monio"""
    minio_server, access_key, secret_key, bucket = 'minio-registry.internalapus.com:9000', \
                                                   'heimdall', '04919f7edbc4107b61fe6c2dfac6d7d6', 'publish-pack'
    return MinioApi(minio_server, access_key, secret_key, bucket)


def sg_minio():
    """新加坡本地monio"""
    minio_server, access_key, secret_key, bucket = '10.11.14.47:9000', 'heimdall', \
                                                   '04919f7edbc4107b61fe6c2dfac6d7d6', 'publish-pack'
    return MinioApi(minio_server, access_key, secret_key, bucket)


if __name__ == '__main__':
    sg_minio().del_pack('deploy_prod/common-service/libra_finance/v1.0.1_d554ff18.tgz')
minio.py

4.Python调用S3的API

Amazon (aws S3) 是一个公开的对象存储服务;

Web 应用程序开发人员可以使用对象存储服务,存储数字资产,包括图片视频音乐和文档;

S3 提供一个 RESTful API 以编程方式实现与S3对象存储服务的交互;

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @file   : awss3.py
# @author : 基础网络-张根
# @date   : 2018/05/30
# @version: 1.0
# @desc   : Aws的S3对象存储服务API,依赖第三方包boto3==1.18.29
from boto3.session import Session
import boto3
import time, os, logging
from datetime import datetime, timedelta

aws_access_key_id = ""
aws_secret_access_key = ""
bucket_name = ""
log_path = "/var/log/awss3.log"
base_data_key = f"fab-browser/mobile-web"
base_data_dir = f"/home/changzhiwei/log/fab_web"


# Crontab每小时执行1次去志伟的目录下查找logfile上传到客户的s3上
class AwsS3API(object):

    def __init__(self):
        auth_dict = {
            'aws_access_key_id': aws_access_key_id,
            'aws_secret_access_key': aws_secret_access_key
        }
        session = Session(**auth_dict)
        self.s3 = session.resource('s3', **auth_dict)
        self.client = boto3.client('s3', **auth_dict)
        self.bucket_name = bucket_name
        self.log_path = log_path

    # 记录日志
    def record_log(self, level, message):
        print(message)
        # Creating and Configuring Logger
        log_format = "%(levelname)s %(asctime)s - %(message)s"
        logging.basicConfig(filename=self.log_path,
                            filemode="a",  # filemode有w和a,w就是写模式,a是追加模式
                            format=log_format,
                            level=getattr(logging, level))  # DEBUG  WARNING  ERROR
        logger = logging.getLogger()
        # Testing our Logger
        getattr(logger, level.lower())(message)

    # 列出查询到的所有对象存储
    def list_object(self, prefix):
        """
        :param prefix: s3对象的key名称开头
        :return:
        """
        retry_count, result, object_list = 1, False, None
        while True:
            try:
                object_list = [file for file in self.s3.Bucket(self.bucket_name).objects.filter(Prefix=prefix)]
            except Exception as error:
                self.record_log("ERROR", error.__str__())
            else:
                if object_list:
                    result = True
            finally:
                retry_count += 1
                if result or retry_count > 3:
                    break
        if object_list is None:
            self.record_log("ERROR", "获取aws s3存储对象失败")
            raise Exception('获取aws s3存储对象失败')
        else:
            return object_list

    # 检测对象是否存在
    def object_exists(self, object_key):
        if self.list_object(object_key):
            return True
        else:
            return False

    # 尝试3次上传文件,并检查是否上传成功
    def upload_object(self, local_file, object_key):
        retry_count, result = 1, False
        while True:
            try:
                self.s3.Object(self.bucket_name, object_key).upload_file(local_file,
                                                                         ExtraArgs={'ACL': 'bucket-owner-full-control'})
            except Exception as error:
                self.record_log("ERROR", "upload_object错误" + error.__str__())
            else:
                self.record_log("DEBUG", '{0} -> {1}/{2} 上传aws s3成功'.format(local_file, self.bucket_name, object_key))
                result = True
            finally:
                retry_count += 1
                if result or retry_count > 3:
                    break
        return result

    # 下载存储库对象
    def download_object(self, object_key):
        if self.object_exists(object_key):
            try:
                self.s3.meta.client.download_file(self.bucket_name, object_key, object_key.split('/')[-1])
            except Exception as Error:
                raise Exception(f'下载{object_key}文件出错,{Error}')
            else:
                self.record_log("DEBUG", f'下载{object_key}成功')
        else:
            raise Exception(f'下载{object_key}出错,存储对象不存在')

    # 删除包
    def del_pack(self, object_key):
        try:
            self.client.delete_object(
                Bucket=self.bucket_name,
                Key=object_key,
            )
        except Exception as Error:
            self.record_log("ERROR", f'删除包错误{str(Error)}')

    # 清理包,保留最新10个
    def clear_pack(self, object_key):
        object_list = self.list_object(object_key)
        key_list = []
        for item in object_list:
            key, last_modified = item.key, item.get().get('LastModified')
            last_stamp = time.mktime(last_modified.timetuple())
            key_list.append((key, last_stamp))
        sorted_list = sorted(key_list, key=lambda x: x[1])
        for item in sorted_list[:-10]:
            self.del_pack(item[0])

    # 上传browser_mobile的数据至客户的aws s3对象存
    def upload_browser_mobile_data(self):
        two_hour_ago = datetime.now() + timedelta(hours=-2)
        two_hour_ago_year, two_hour_ago_month, two_hour_ago_day, two_hour_ago_hour = (two_hour_ago.year,
                                                                                      two_hour_ago.month if two_hour_ago.month > 9 else f"0{two_hour_ago.month}",
                                                                                      two_hour_ago.day if two_hour_ago.day > 9 else f"0{two_hour_ago.day}",
                                                                                      two_hour_ago.hour if two_hour_ago.hour > 9 else f"0{two_hour_ago.hour}"
                                                                                      )
        time_flag = f"year={two_hour_ago_year}/month={two_hour_ago_month}/day={two_hour_ago_day}/hour={two_hour_ago_hour}"
        log_data_dir, log_data_key = f"{base_data_dir}/{time_flag}", f"{base_data_key}/{time_flag}"
        [self.upload_object(os.path.join(log_data_dir, lf), os.path.join(log_data_key, lf)) for lf in
         os.listdir(log_data_dir)] if os.listdir(log_data_dir) else self.record_log("ERROR",
                                                                                    f"{log_data_dir}目录下下不存在日志文件")


if __name__ == '__main__':
    s3_obj = AwsS3API()
    s3_obj.upload_browser_mobile_data()
awss3.py

 

Docker Compose

 

虽然可以通过Dockerfile文件很方便的定义1个单独的容器。

然而,在日常工作中我们的项目架构会设计MySQL、Nginx、Redis等各种组件搭配在一起工作。

这时我就是需要使用Docker Compose容器编排工具,对多个容器进行编排。

 

DockerCompose和DockerSwarm/k8s 的区别

Docker compose和Docker swarm 都是Docker官方容器编排工具,

单不同的是Docker Compose是一个在单个服务器或主机上创建多个容器的工具。

而Docker Swarm则可以在多个服务器或主机上创建容器集群服务还可以实现对服务器资源的分配和调度

 

Docker-Compose简介

Compose 项目是Docker官方开源的项目,负责实现对多个Docker 容器进行快速编排。

Docker Compose的使用简单基本上分为3个步骤:

  • 使用Dockerfile定义单个容器的运行环境
  • 使用docker-compose.yml文件定义构建当前项目所依赖的容器,这样这些容器就可以在不同的隔离环境中被运行分别运行。=
  • 执行1个 dokcer-compose up 命令,来启动容器组(当前项目所依赖的所有容器)。
docker-compose up     开启一组容器
docker-compose down 关闭一组容器       

 

Docker-Compose 核心概念

服务(service):一个应用的容器。服务可以存着多个。

项目(project):由一组相互之间关联的容器,组成的一个完整业务单元。 项目在docker-compose.yml中进行定义。

Docker-Compose安装

[root@VM-0-5-centos ~]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:06 --:--:--     
[root@VM-0-5-centos ~]# ls -l /usr/local/bin/docker-compose 
-rw-r--r-- 1 root root 16168192 Jun  9 10:31 /usr/local/bin/docker-compose
[root@VM-0-5-centos ~]# chmod +x /usr/local/bin/docker-compose 
[root@VM-0-5-centos ~]# docker-
docker-compose  docker-init     docker-proxy    
[root@VM-0-5-centos ~]# docker-
docker-compose  docker-init     docker-proxy    
[root@VM-0-5-centos ~]# docker-compose -v
docker-compose version 1.24.1, build 4667896b
[root@VM-0-5-centos ~]# 

 

Docker-compose.yml

Docker-compose.yml是来定义当前项目的文件,它遵循一些语法格式。

version: "3.0" #docker-compose的版本号
services: #一组相互之间有业务联系的服务组

  protainer:
    image: :portainer/portainer
    container_name: protainer_container
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /protainer:protainer
    networks:
      - api
    ports:
      - "8000:8000"
      - "9000:9000"

  buget-api:
    build:  #直接把Dockerfile打包成镜像并运行
      context: ./  #指定Dockerfile所在的目录
      dockerfile: Dockerfile  #Dockerfile的文件名称
    container_name: buget-apicontainer  #容器名称
    ports:
      - 8090:8090""
    networks:
      - apai-network
    depends_on:
      - nginx

  nginx:   #服务
    image: nginx   #使用的镜像
    ports:     #使用的端口
      - "80:80"
    volumes: #完成宿主机和容器目录卷的映射
      - zhanggen:/zhanggen  #宿主机的目录


volumes:
  zhanggen:
    external:
      flase

 

在docker-compose.yml引用环境变量

[root@VM-0-5-centos docker]# cat .env
nginx=nginx
[root@VM
-0-5-centos docker]# cat docker-compose.yml version: "3.0" #docker-compose的版本号 services: #一组相互之间有业务联系的服务组 nginx: #服务 image: ${nginx} #使用的镜像 ports: #使用的端口 - "80:80" volumes: #完成宿主机和容器目录卷的映射 - zhanggen:/zhanggen #宿主机的目录 volumes: zhanggen: [root@VM-0-5-centos docker]#

 

Docker-compose

我使用Dockerfile的mutistage-build语法定义了1个可以被多个web项目重复FROM的,web开发环境。

FROM python:3.7.6 AS pure_python_env
MAINTAINER franplk
LABEL version=1.0 description=HunanModelSystem

FROM pure_python_env AS python_site_package
WORKDIR /root
COPY requirements.txt  requirements.txt
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple


FROM python_site_package AS uwsgi_builder
WORKDIR /root
COPY uwsgi/uwsgi-2.0.19.1 uwsgi-2.0.19.1
RUN mv uwsgi-2.0.19.1 uwsgi
WORKDIR /root/uwsgi
RUN make && ln -s /root/uwsgi/uwsgi /usr/bin/uwsgi
EXPOSE 8099
WORKDIR /root
CMD uwsgi --ini /${PROJECT_NAME}/devops/docker/uwsgi/uwsgi.ini

 

我使用Docker-compose定义了1个L+N+M+P(Python)的web运行环境。

version: "3.0" #docker-compose的版本号
services: #一组相互之间有业务联系的服务组
  mysql: #MySQL服务
        environment:
            TZ: "Asia/Shanghai"
            MYSQL_ROOT_PASSWORD: "weike@2020"
            MYSQL_USER: 'zhanggen'
            MYSQL_PASS: 'weike@2020'
        image: mysql:5.7
        container_name: BudgetAPIMySQLContainer  #容器名称
        restart: always
        volumes:
              #MySQL数据存储目录
            - "./mysql/data:/var/lib/mysql"
             #MySQL配置文件
            - "./mysql/conf/my.cnf:/etc/my.cnf"
             #MySQL初始化执行
            - "./mysql/init:/docker-entrypoint-initdb.d/"
        ports:
            - "3304:3303"
        networks:
            - budget_api


  nginx:   #nginx服务
    container_name: BudgetAPINginxContainer  #容器名称
    image: nginx:1.21.0   #使用的镜像
    environment:
      - TZ=Asia/Shanghai
    ports:     #使用的端口
      - "8088:8080"
      - "444:443"
    extra_hosts:
      - "uwsgi_host:115.159.55.242"

    volumes: #完成宿主机和容器目录卷的映射
      - ./nginx/config/nginx.conf:/etc/nginx/nginx.conf  #配置
      - ./nginx/log:/var/log/nginx #日志
      - ../../code/resources/static:/static #静态文件
    networks:
      - budget_api


  budget_api:  #flask进程
    build:  #直接把Dockerfile打包成镜像并运行
      context: "./"  #指定Dockerfile所在的目录
      dockerfile: Dockerfile  #Dockerfile的文件名称
    image: budget_api:v1
    extra_hosts:
      - "mysql_host:115.159.55.242"

    container_name: BudgetAPIProjectContainer  #容器名称
    environment:                               #设置容器的运行模式
      - PROJECT_NAME=budget-api                  #Dockerfile中使用的环境变量
      - RUN_ENV=release                          #项目启动时选择的运行环境
    volumes:
      - ../../../budget-api:/budget-api/
      - /mingde/projects/models/model_similarity.bin:/root/model_similarity.bin
    ports:
      - "8091:8099"
    networks:
      - budget_api
    depends_on:
      - mysql
      - nginx


networks:
  budget_api:
      driver: bridge

 

Mysql在容器中的备份和恢复

[root@VM-0-5-centos backup]# pwd
/mingde/projects/HunanModel/devops/docker/mysql/backup
[root@VM-0-5-centos backup]# docker exec MySQLContainer /usr/bin/mysqldump -u root --password=Password db_hunan_model > ./db_hunan_model.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@VM-0-5-centos backup]# cat ./db_hunan_model.sql | docker exec -i MySQLContainer /usr/bin/mysql -u root --password=Password db_hunan_model
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@VM-0-5-centos backup]# 

 

 

Docker问题汇总

1.宿主机无法访问Docker网络

增加sudo权限

vim /etc/sudoers

root    ALL=(ALL)       ALL
appuser ALL=(ALL)       NOPASSWD: ALL

先关闭docker引擎

service docker stop

关闭docker0的网卡

ip link set dev docker0 down

删除docker0网桥

brctl delbr docker0

重建docker0网桥

brctl addbr docker0

设置IP段

ip addr add 172.17.42.2/24 dev docker0

启动docker0网桥

ip link set dev docker0 up

重启docker引擎

service docker start

 测试

            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "c2be63b76bb888ec4bcddfe9c7c7ff9267b721c31cd92c8f114beab390082b84",
                    "EndpointID": "8ae0707da7f4f5d575e60d0d2cd0be8a39334e1b68f83fbde1621317cc9d51f7",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
[root@zhanggen mingde]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.058 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.057 ms

 

 

dockerCompose

posted on 2019-03-19 09:19  Martin8866  阅读(3937)  评论(1编辑  收藏  举报