一、容器技术概述

为什么使用容器?

我们需要先了解程序部署的历史演进,在早期是没有什么虚拟机或容器这种概念的,起初一切都部署在物理机,即程序运行在搭载有操作系统的主机上,随着时代的发展,出现各种类型的应用,部署在物理机上的程序要么计算资源和存储资源都不够用,要么资源过剩造成浪费。所以出现了虚拟机技术,在物理机的基础上运行虚拟机软件,把系统的计算资源或存储资源进行切分,程序则运行在虚拟机层面,以达到充分使用资源的目的。但虚拟机的解决方案本身存在着一些问题,一方面虚拟化Hypervisor管理软件本身的资源消耗与磁盘IO性能降低,另一方面是虚拟机仍然还是一个独立的操作系统,对很多类型的业务应用来说都显得太重了,导致我们在处理虚拟机的扩缩容与配置管理工作时效率低下。为了解决虚拟机技术的这些缺陷,所以演化出了容器技术,基于容器的应用可以直接运行在物理主机的操作系统之上,可以直接读写磁盘,应用之间通过计算、存储和网络资源的命名空间进行隔离,为每个应用形成一个逻辑上独立的“容器操作系统”。除此之外,容器技术还有简化部署、多环境支持、快速启动、服务编排、易于迁移等优点。

虚拟机与容器技术.jpg

二、Docker概述及基本使用

1.Docker概述

Docker是什么?
  • Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
  • Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
  • 容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker应用场景
  • Web 应用的自动化打包和发布。
  • 自动化测试和持续集成、发布。
  • 在服务型环境中部署和调整数据库或其他的后台应用。
  • 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
Docker技术有哪些优势
  • 简化程序:

Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的 任务,在Docker容器的处理下,只需要数秒就能完成。

  • 节省开支:

云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。

2.Docker的基本使用

2.1 基本概念
header 1 header 2
Docker Daemon Docker守护进程,用户通过docker daemon管理物理机上的镜像、容器、仓库等相关操作,它是容器构建的引擎。
Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板。
Docker 容器(Container) 容器是独立运行的一个或一组应用。
Docker 客户端(Client) Docker 客户端通过命令行或者其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api) 与 Docker 的守护进程通信。
Docker 主机(Host) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker 仓库(Registry) Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。
Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。
Docker架构.png
2.2 docker 命令简述
Docker Daemon

安装docker后默认启动守护进程,你可以通过docker client 使用命令管理镜像、容器、仓库等。

终端输入后查看相关命令:

docker help
Usage:  docker [OPTIONS] COMMAND
A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/Users/fun/.docker")
  -D, --debug              Enable debug mode   
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/Users/fun/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/Users/fun/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/Users/fun/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

分组管理命令:
  builder     管理构建镜像
  config      管理docker配置
  container   管理容器
  image       管理镜像
  network     管理网络
  node        管理群节点
  plugin      管理插件
  secret      管理加密
  service     管理服务
  stack       管理栈
  swarm       管理群
  system      管理docker系统
  trust       管理信任镜像
  volume      管理存储卷

快捷命令:
  attach      将本地标准输入、输出和错误流附加到正在运行的容器
  build       从Dockerfile构建镜像
  commit      根据容器的更改创建新镜像
  cp          在容器和本地文件系统之间复制文件/文件夹
  create      创建新容器
  diff        检查对容器文件系统上文件或目录的更改
  events      从服务器获取实时事件
  exec        在正在运行的容器中运行命令
  export      将容器的文件系统导出为tar存档
  history     显示镜像的历史记录
  images      列表镜像
  import      从tarball导入内容以创建文件系统映像
  info        显示系统范围的信息
  inspect     返回Docker对象的低级信息
  kill        杀死一个或多个正在运行的容器
  load        从tar存档或stdin加载镜像
  login       登录Docker仓库
  logout      从Docker仓库注销
  logs        获取容器的日志
  pause       暂停一个或多个容器中的所有进程
  port        列出容器的端口映射或特定映射
  ps          列表容器
  pull        从仓库中提取镜像或存储库
  push        将映像或存储库推送到仓库
  rename      重命名容器
  restart     重新启动一个或多个容器
  rm          移除一个或多个容器
  rmi         删除一个或多个镜像
  run         在新容器中运行命令
  save        将一个或多个镜像保存到tar存档(默认流到stdout)
  search      DockerHub中搜索镜像
  start       启动一个或多个停止的容器
  stats       显示容器资源使用统计信息的实时流
  stop        停止一个或多个正在运行的容器
  tag         创建引用源镜像的标记目标镜像
  top         显示容器的运行进程
  unpause     取消暂停一个或多个容器中的所有进程
  update      更新一个或多个容器的配置
  version     显示Docker版本信息
  wait        阻塞直到一个或多个容器停止,然后打印其退出代码

Run 'docker COMMAND --help' for more information on a command.
Dcoker镜像

docker镜像是容器运行的模板,在容器运行前先要拉取镜像或自己创建镜像。

创建镜像的三种方式:
1.从镜像仓库拉取已发行的镜像,根据这个镜像启动容器,使用commit命令生成自己的本地镜像;
2.使用Dockerfile文件,根据Dockerfile语法编写镜像构建命令,再使用docker build生成本地镜像;
3.从零开始编写镜像,一般只有专业镜像团队创建。

  • 镜像管理基本命令
docker image --help
Usage:  docker image COMMAND
Manage images
Commands:
  build       根据Dockerfile构建镜像
  history     打印一个镜像的历史记录
  import      从Dockerfile导入内容以创建文件系统映像
  inspect     显示一个或多个镜像的详细信息
  load        从tar压缩包或终端标准输入加载一个镜像
  ls          打印镜像列表
  prune       移除一个没有用的镜像
  pull        从镜像仓库站拉取一个镜像或一个镜像储存库
  push        推送一个镜像或一个镜像储存库到镜像站
  rm          移除一个或多个镜像
  save        保存一个或多个镜像到tar压缩包
  tag         给一个镜像打标签版本


Run 'docker image COMMAND --help' for more information on a command.

拉取镜像简单示例:

//从镜像仓库拉取alpine镜像
docker pull alpine:latest 

删除镜像

//删除所有未打 dangling 标签的镜像
docker rmi (docker images -q -f dangling=true)

//删除所有镜像
docker rmi(docker images -q)

//强制删除镜像名称中包含“doss-api”的镜像
docker rmi --force (docker images | grep doss-api | awk '{print3}')
  • 使用Dockerfile构建镜像
    Dockerfile里的命令声明:
类别 命令
基础镜像信息 FROM
维护者信息 MAINTAINER
镜像操作指令 RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令 CMD、ENTRYPOINT

FROM:指定哪种镜像作为新镜像的基础镜像;

MAINTAINER:指明该镜像的作者和其电子邮件;

RUN:在新镜像内部执行的命令,比如安装一些软件、配置一些基础环境,可使用来换行

COPY:将主机的文件复制到镜像内,如果目的位置不存在,Docker会自动创建所有需要的目录结构,但是它只是单纯的复制,并不会去做文件提取和解压工作。

ADD:将主机的文件复制到镜像中,跟COPY一样,限制条件和使用方式都一样

EXPOSE:暴露镜像的端口供主机做映射,启动镜像时,使用-P参数来讲镜像端口与宿主机的随机端口做映射。使用方式(可指定多个)

WORKDIR:在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录。

ONBUILD
当一个包含ONBUILD命令的镜像被用作其他镜像的基础镜像时(比如用户的镜像需要从某为准备好的位置添加源代码,或者用户需要执行特定于构建镜像的环境的构建脚本),该命令就会执行。

USER:指定该镜像以什么样的用户去执行

VOLUME:用来向基于镜像创建的容器添加卷。比如你可以将mongodb镜像中存储数据的data文件指定为主机的某个文件。(容器内部建议不要存储任何数据)

CMD:容器启动时需要执行的命令

ENTRYPOINT 作用和用法和CMD一模一样

CMD和ENTRYPOINT同样作为容器启动时执行的命令,区别有以下几点:

1.CMD的命令会被 docker run 的命令覆盖而ENTRYPOINT不会;

2.CMD和ENTRYPOINT都存在时,CMD的指令变成了ENTRYPOINT的参数,并且此CMD提供的参数会被 docker run 后面的命令覆盖。

使用示例:使用Dockerfile构建一个精简的linux系统发行版

Dockerfile文件:

FROM alpine:latest 

运行打包镜像

docker build -t alpine_demo:v0.1 ./

Docker容器

容器是docker实际的运行单元,用户根据镜像启动容器来提供服务。

  • 容器管理基本命令
docker container --help
Usage:  docker container COMMAND
Manage containers

Commands:
  attach      将本地标准输入、输出和错误流附加到正在运行的容器
  commit      根据容器的更改创建新镜像
  cp          在容器和本地文件系统间拷贝文件或文件夹
  create      创建一个新容器
  diff        检查对容器文件系统上文件或目录的更改
  exec        在一个运行的容器上执行命令
  export      将容器的文件系统导出为tar存档
  inspect     在一个或多个容器上显示详细信息
  kill        杀死一个或多个容器
  logs        获取容器的日志
  ls          打印容器列表
  pause       暂停一个或多个容器中的所有进程
  port        列出容器的端口映射或特定映射
  prune       移除所有已经停止运行的容器
  rename      重命名一个容器
  restart     重启一个或多个容器
  rm          移除一个或多个容器
  run         在新容器中运行命令
  start       启动一个或多个已经停止的容器
  stats       显示容器资源使用统计信息的实时流
  stop        停止运行一个或多个容器
  top         显示容器的运行进程
  unpause     取消暂停一个或多个容器中的所有进程
  update      更新一个或多个容器的配置
  wait        阻塞直到一个或多个容器停止,然后打印其退出代码



Run 'docker container COMMAND --help' for more information on a command.
  • 基于镜像启动容器
docker run -t -name=myalpine alpine_demo:v0.1
//or
docker container run -t -name=myalpine alpine_demo:v0.1
  • 关闭/暂停/杀死容器
//批量删除已经终止运行的容器:
docker ps -a|grep Exited|awk '{print 1}'

//杀死所有正在运行的容器
docker kill(docker ps -a -q)

//删除所有已经停止的容器
docker rm $(docker ps -a -q)

三、使用Docker部署Go程序

编写一个基本的web服务demo_service/main.go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

//搭建基本的http服务器 http_server.go
func main() {

    //设置http服务处理函数
    http.HandleFunc("/hi", func(writer http.ResponseWriter, request *http.Request) {
        writer.Write([]byte("Hi Gopher!!!"))
    })


    //服务绑定端口并启动服务
    http.ListenAndServe("0.0.0.0:8888", nil)
    fmt.Println("服务端已启动....监听端口:8888")
}
编写Dockfile
#alpine是最精简的linux系统发行版
FROM alpine:latest

#镜像构建时创建目录/app
RUN mkdir /app
#切换工作目录为/app
WORKDIR /app

#从宿主机文件系统拷贝可执行文件到容器的工作目录
ADD demo_service /app/demo_service

#容器启动时执行可执行程序
CMD ["./demo_service"]
编写Makefile

在实际项目中你可能一次要构建多个服务,建议使用Makefile编写构建命令:

buildgo:
    #   1.编译linux版的运行文件。将go源码编译成目标系统为amd64 CPU的linux系统环境
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./demo_service mydemo/demo_service

builddocker:
    #   2.将运行文件容器化,打包镜像。根据当前目录下的Dockerfile生成镜像,把go服务容器化
    docker build -t demo_service:v0.1 ./

rundocker:
    #   3.运行。将镜像运行到容器,宿主机端口8080映射容器端口8888,通过设置容器运行的环境变量的方式
    docker run -p 8080:8888 
         -e MICRO_SERVER_ADDRESS=:8080 
         --rm   
         --name demo_server 
         demo_service:v0.1

启动Docker容器
make

在Makefile当前目录运行make命令,就在docker启动了容器服务,
在浏览器输入 http://localhost:8080/hi 即可访问服务!

小结

容器技术在现代应用的构建中有举足轻重的作用,随着分布式微服务的架构越来越盛行,容器技术作为基础设施其热度只增不减,而Docker作为最热门的容器管理引擎,我们有必要学好容器技术,此专题只是抛砖引玉,带你了解容器技术和Docker的简单使用,建议开发者系统地学习Docker技术,以及更深入的容器编排等技术,如当下盛行的K8s。至此容器专题暂时讲到这,感谢阅读,如发现有误,欢迎指正。

文章来源于互联网:13 Go与Docker容器技术

发表评论