logo头像

分享技术,品味人生

docker

一、物理机/虚拟机准备

[!tip] > docker-ce 需要内核3.10以上版本,所以centos7的版本要尽量新,否则容易安装不成功

  • 克隆虚拟机模板, 设置IP为192.168.20.150,虚拟机安装之克隆安装
# 一、克隆安装
- 选择已经准备好并关机的模板服务器170,右键进行克隆
- 执行脚本配置ip、主机名
    - vcenter控制可考虑用图形化工具进行配置和激活, ==nmtui== , 设置ip网关及主机名


hostnamectl set-hostname test1.dev.lzh
bash
sed -i 's/192.168.20.170/192.168.20.161/' /etc/sysconfig/network-scripts/ifcfg-ens192
systemctl restart network
ip a s
hostname -s
hostname -f
ip r
  • 安装后测试是否可远程连接,ok后关机
  • 关闭防火墙及安全设置(全新安装才需要,模板已统一设置,故可以跳过)
#---------------------------------------------------------- 
# 建议关闭的初始化操作
#---------------------------------------------------------- 

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭Selinux
setenforce 0
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 关闭SWAP
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab

# 设置主机名
hostnamectl set-hostname template
bash

二、Docker 环境安装

  • 设置阿里云的源,安装docker-ce
cd /etc/yum.repos.d/
rename .repo .repobak ./*

wget -O /etc/yum.repos.d/aliyun-centos7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/aliyun-centos-docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum clean all
yum makecache fast
yum update -y
yum repolist


yum install -y yum-utils device-mapper-persistent-data lvm2
yum install -y docker-ce
systemctl stop firewalld
systemctl disable firewalld
systemctl enable docker
systemctl start docker

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://6yga1re5.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
docker --version
  • docker hello world (注:run模式下,执行即结束,后端遗留垃圾容器)
docker run ubuntu:16.04 /bin/echo "Hello world"

# 进入容器内,退出容器消亡,但还遗留
docker run -it  ubuntu:16.04 /bin/bash

三、Docker日常维护

2.1、镜像操作

  • dockerHub镜像操作
# web查询,访问 https://hub.docker.com
# 拉取最新镜像, 不写tag,默认拉取latest
docker pull nginx

# 查看latest实际版本
docker image inspect nginx:latest | grep -i version

# 拉取指定版本,建议去hub的tags标签页查找
docker pull nginx:1.20

# 删除dangling 悬挂镜像
docker rmi $(docker images -f "dangling=true" -q)
  • 本地镜像操作
# 查看本地镜像清单
docker images

# 导出镜像为tar
docker save -o nginx.tar nginx:latest

# 删除镜像, 无标记,默认删除lastest
docker rmi nginx

# 导入镜像
docker load -i nginx.tar

# tag标记或备份?
docker tag nginx:latest nginx:lin

2.2、容器操作

  • dockerHub镜像操作
# 运行一个容器,并设置名称、端口【宿主机:容器端口】、后端运行、镜像:版本号
docker run --name mn -p 80:80 -d nginx:latest

# 查看运行或暂挂的容器, -a 可看到停止的容器
docker ps

# 查看容器日志
docker logs mn

# 进入容器bash, 退出直接exit
docker exec -it mn bash

# 不进入容器,直接修改容器内文件
docker exec -it mn \
          sed -i 's#Welcome to nginx#lin baba welcome#g' \
                /usr/share/nginx/html/index.html

# 暂停、恢复容器
docker pause mn
docker unpause mn

# 停止并删除容器
docker stop mn
docker ps -a
docker rm mn


# 日志驱动??
docker run -d \
– log-driver=fluentd \
– log-opt fluentd-address=10.2.3.4:24224 \
– log-opt tag=”docker.{{.Name}}” \
nginx

2.3、数据卷及目录挂载

  • 数据卷挂载实验, 宿主机本地默认目录
# 创建数据卷、检阅、prune无使用删除方式
docker volume create html
docker volume inspect html
docker inspect html
docker volume prune -f

# 再次创建数据卷,运行nginx容器并关联
docker volume create html
docker inspect html
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx 
docker ps
curl localhost

# 测试容器被删除后,数据卷内文件保存, 因此也证明了卷内的文件是从只读的容器拷贝过来的!而非简单链接使用
docker rm -f mn
ls -l /var/lib/docker/volumes/html/_data
sed -i 's#Welcome to nginx#lin baba welcome#g' \
       /var/lib/docker/volumes/html/_data/index.html 
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx

# 删除容器、删除卷、重新运行容器并标识数据卷,自动创建数据卷!
docker rm -f mn
docker ps -a
docker volume ls
docker volume prune
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
  • 目录挂载,更灵活
docker pull  mysql:5.7.37
mkdir -p /tmp/mysql/{conf,data}

tee /tmp/mysql/conf/hmy.cnf <<-'EOF'
[mysqld]
skip-name-resolve
character_set_server=utf8
datadir=/var/lib/mysql
server-id=1000
EOF

docker run \
    --name mysql \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=123456 \
    -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
    -v /tmp/mysql/data:/var/lib/mysql \
    -d mysql:5.7.37
    

四、网络

五、dockerFile定制镜像

# prepare
docker pull nginx:stable


mkdir -p /usr/local/docker/nginx_docker/html
cd /usr/local/docker/nginx_docker/
echo "<center>hello linbaba</center>" > /usr/local/docker/nginx_docker/html/index.html

tee Dockerfile <<-'EOF'
FROM nginx:stable
MAINTAINER linzhihui <linzhihui@hotmail.com>
COPY ./html/index.html /usr/share/nginx/html
EOF

docker build -t mynginx:v1.0.1 .
docker tag mynginx:v1.0.1 mynginx:latest

docker run -it --rm --name web\
       -p 8081:80 \
       -d mynginx:latest

docker stop web

六、dockerCompose使用

curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
  • 测试,py+redis的compose组合


mkdir /tmp/composetest && cd /tmp/composetest

tee /tmp/composetest/app.py <<-'EOF'
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)


def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)


@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
EOF


tee /tmp/composetest/requirements.txt <<-'EOF'
flask
redis
EOF

tee /tmp/composetest/Dockerfile <<-'EOF'
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
EOF

tee /tmp/composetest/docker-compose.yml <<-'EOF'
# yaml 配置
version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"
EOF

docker-compose up -d
docker-compose down

七、Docker 仓库

7.1、registry

7.2、habor

  • docker的仓库是默认registry,vm家的habor功能更强大和主流
  • gg搜索gohabor,从官网进入github下载离线tgz包

7.2.1、Habor安装配置

tar zxvf harbor-offline-installer-v2.5.0.tgz -C /usr/local/
/usr/local/harbor/
cp harbor.yml.tmpl harbor.yml

# 修改hostname和端口,并注释掉https和证书
./install.sh 

# web访问 admin/Harbor12345, 修改密码,添加项目repo公开仓库

7.2.2、linux/docker宿主机上传、下载测试

tee /etc/docker/daemon.json <<-'EOF'
{
  "insecure-registries": ["192.168.20.151:80"]
}
EOF
systemctl restart docker
cd /usr/local/harbor
docker-compose up -d

docker tag demo:v1.0.0 192.168.20.151:80/repo/demo:v1.0.0
docker login -u admin -p Harbor12345 192.168.20.151:80
docker push 192.168.20.151:80/repo/demo:v1.0.0

# 删除本地,再从网络拉取
docker rmi 0ace52fd71b4 -f
docker pull 192.168.20.151:80/repo/demo:v1.0.0

7.2.3、整合jenkins-整合宿主机docker、打包上传镜像

cd /var/run/
chown root:root docker.sock
chmod o+rw docker.sock

# 修改compose文件,增加3个docker文件支持,方便使用宿主机进行docker镜像打包
cd /usr/local/docker/jenkins_docker
tee docker-compose.yml <<-'EOF'
version: '3.1'
services:
  jenkins:
    image: 'jenkins/jenkins:2.319.1-lts'
    container_name: jenkins
    ports:
      - '8080:8080'
      - '50000:50000'
    volumes:
      - './data:/var/jenkins_home'
      - '/var/run/docker.sock:/var/run/docker.sock'
      - '/usr/bin/docker:/usr/bin/docker'
      - '/etc/docker/daemon.json:/etc/docker/daemon.json'
EOF

docker-compose up -d
docker exec -it jenkins bash
# 检查docker是否整合成功
docker version

image-20220428092907724

# 可以去除构建后操作和compose文件,在构建成功后,添加以下shell

mv target/*.jar docker/
docker build -t mytest:$demoProjectTag docker/
docker login -u admin -p Harbor12345 192.168.20.151:80
docker tag mytest:$demoProjectTag 192.168.20.151:80/repo/mytest:$demoProjectTag
docker push 192.168.20.151:80/repo/mytest:$demoProjectTag

7.2.4、整合jenkins-通知、下载镜像

  • 准备shell脚本,并手工测试
mkdir /usr/local/test
cd /usr/local/test
tee deploy.sh <<-'EOF'
#!/bin/bash
harbor_addr=$1
harbor_repo=$2
project=$3
version=$4
host_port=$5
container_port=$6

imageName=$harbor_addr/$harbor_repo/$project:$version
echo $imageName

containerId=`docker ps -a|grep ${project} | awk '{print $1}'`
echo $containerId

if [ "$containerId" != "" ] ; then
  docker stop $containerId
  docker rm $containerId
fi

tag=`docker images |grep ${project} | awk '{print $2}'`

if [[ "$tag" =~ "$version" ]] ; then
  docker rmi $imageName
fi

docker login -u admin -p Harbor12345 $harbor_addr
docker pull $imageName
docker run -d -p $host_port:$container_port --name $project $imageName

echo "SUCCESS"
EOF

chmod +x deploy.sh

./deploy.sh 192.168.20.151:80 repo demo v2.0.0 8081 8080
  • 整合jenkins, 添加构造后的操作、端口参数,便于日常调整
    image-20220428102539526
    image-20220428102600718
/usr/local/test/deploy.sh 192.168.20.151:80 repo demo $demoProjectTag $host_port $container_port

7.2.5、整合jenkins-发送webhook到dingtalk/微信

  • 企业微信
    • 先拉两人建群聊,添加机器人,获得webhook地址,及使用帮助
    • jenkins 安装qy wechat插件
    • 在构建后添加企业微信通知接口,pipeline方式下面有,比较麻烦
  • 钉钉
    • 基本类似企业微信,pipiline效果看上去还可以,具体未尝试,可参考哔哩哔哩_bilibili
  • 微信
    • 无webhook接口,不过可借助第三方,搜索pushplus

八、dockerSwarm

1

九、有趣的应用

9.1、时区设置

  • alpine时区设置(现成镜像)
    • 注:查看是哪个发行版本 cat /etc/issue
# 进入镜像,设置阿里源,安装tzdata,设置本地时间和时区,然后清理tzdata
docker exec -it demo2 sh

echo -e  "http://mirrors.aliyun.com/alpine/v3.4/main\nhttp://mirrors.aliyun.com/alpine/v3.4/community" \
 >  /etc/apk/repositories && apk update

apk add tzdata

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

echo "Asia/Shanghai" > /etc/timezone

apk del tzdata

# 检查,看时间是不是从+0到+8
date -R
  • alpine时区设置(dockerFile)
# dockerfile文件中填入这段
# alpine基础镜像修改默认时区为上海
RUN echo -e  "http://mirrors.aliyun.com/alpine/v3.4/main\nhttp://mirrors.aliyun.com/alpine/v3.4/community" >  /etc/apk/repositories \
&& apk update && apk add tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Shanghai/Asia" > /etc/timezone \
&& apk del tzdata
  • debian时区设置(dockerFile)
# dockerfile文件中填入这段
ENV TZ=Asia/Shanghai \
    DEBIAN_FRONTEND=noninteractive

RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata \
    && rm -rf /var/lib/apt/lists/*
  • debian时区设置(现成镜像)
ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 
echo Asia/Shanghai > /etc/timezone 
dpkg-reconfigure --frontend noninteractive tzdata
rm -rf /var/lib/apt/lists/*
  • debian时区设置(容器启动或创建时指定参数)
# -e TZ=Asia/Shanghai 
docker run -e TZ=Asia/Shanghai -p 8081:8080 --rm -d --name demo2 demo:1.0 
  • busybox-helloworld
yum install glibc-static -f

mkdir -p /tmp/busybox && cd /tmp/busybox
tee /tmp/busybox/hello.c <<-'EOF'
#include <stdio.h>
int main(){
    printf("hello busybox\n");
}
EOF

gcc hello.c -static -o hello

tee /tmp/busybox/Dockerfile <<-'EOF'
FROM busybox
ADD hello /
CMD ["/hello"]
EOF

docker build -t myhello .

docker images

docker run --name myhello -d myhello
docker logs myhello
  • 指定jdk的最小基础镜像
docker pull jeanblanchard/busybox-java
  • java demo
tee /tmp/busybox/Dockerfile <<-'EOF'
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝jdk和java项目的包
COPY ./jdk1.8.0_144 $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar

# 安装JDK
RUN cd $JAVA_DIR \
 && ln -s ./jdk1.8.0_144 ./java8

# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
EOF


docker rm -f javaweb \
    && docker build -t javaweb:1.3 . \
    && docker tag javaweb:1.3 javaweb:latest

docker run --name javaweb -p 8090:8090 -d javaweb
  • 轻量级jdk,相比ubuntu,从537MB降到171,少了366MB
tee /tmp/busybox/Dockerfile <<-'EOF'
# 指定基础镜像
FROM java:8-alpine

# 拷贝java项目的包
COPY ./docker-demo.jar /tmp/app.jar

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
EOF


docker rm -f javaweb \
    && docker build -t javaweb:2.0 . \
    && docker tag javaweb:2.0 javaweb:latest

docker run --name javaweb -p 8090:8090 -d javaweb

评论系统未开启,无法评论!