Docker入门

一.Docker介绍及安装

  Docker是容器技术的一个代表,容器技术从本质上讲是将程序隔离、打包的技术,不是一个很新的技术,核心的技术在内核里已经存在很久了,但这个技术真正被大家所用,变成这么流行、这么火爆的技术是因为Docker,Docker在2013年开源后发展的非常非常快。

  Docker在云计算领域是一个非常火热的话题,Docker很好的理顺了开发和运维的环境的差异,使得开发和运维可以用同一个语言来沟通,另外,Docker和现在的deops、持续集成、持续交互、微服务等概念都是相辅相成的。

1.什么是Docker

  Docker是一个开源的项目,它可以用来将任何应用以轻量级容器的形式来打包、发布和运行。在Node.js上是这样说Docker的:Docker允许一个应用程序及其所有依赖以一种标准的单位来打包。

  类比:

  可以粗糙地理解为轻量级的虚拟机

  开挂的chroot

  Docker确实不是虚拟机

  Docker有一个Docker Engine层,在其上运行各种各样的程序,它是利用了Host OS里面的NameSpace、Control Group这些来做到将应用程序分离,因为它没有虚拟层这一个,会比虚拟机轻很多,程序启动速度、内存、存储需求都会小很多。

2.docker安装

a.mac安装

  下载、安装、配置。

  安装好后,可以执行docker info查看信息。

  配置的话,由于docker官网很慢,可以在Registry mirrors中配置加速器,其实就是国内镜像。如阿里云、时速云等,去注册一个账号,就可以得到一个专属的加速器的地址,重启Docker即可。

b.Linux安装‘

  $sudo wget -qO- https://get.docker.com | sh:安装Docker本身,wget是命令行的下载工具,它来下载https://get.docker.com这个地址,-q是让wget不要输出那么多,-O-意思是把wget的输出直接输出到标准输出(而不是输出到文件),然后用到管道的概念,把输出给后面的sh执行。这个命令会检测你的Linux的版本,根据你的版本用比较合适的安装包来安装,然后启一个服务。

  $sudo usermod -aG docker imooc:修改用户的组,把imooc用户加到docker组,这样就允许非super user运行Docker,因为缺省安装后只允许root来执行。

c.Windows安装

二.Docker架构介绍与实践

  中间是我们进行Docker操作的虚拟机,它运行了一个叫做Docker daemon的程序,这个程序负责做各种各样的Docker操作,比如下载镜像、运行一个容器,我们是通过Client用命令(如build、pull、run)交给Docker daemon,由Docker daemon来做实际的操作,右边是Registry,Docker daemon可以和它去交互,拖取一个image,或者push一个image,它是所有Docker玩家共享Docker镜像的服务。

  这是一张中文版的架构图,客户端和守护进程进行操作,把命令送给守护进程,守护进程来拖取镜像、运行容器、并且和远端的镜像仓库进行交互。

  用ubuntu这个image,在这里面运行了一个echo hello docker命令,输出就是hello docker。

  docker run -p 8080:80 -d nginx命令返回一串字符串,这串字符串是Docker CONTAINER ID,-p是做端口映射的,是把Docker nginx本身的80端口映射到本地Host的8080端口,-d是允许这个程序直接返回,就是把这个容器做为守护进程来运行的。

  docker ps可以看到当前正在运行的Docker容器,其中就是我们刚刚运行的CONTAINER ID 2b2eec668c76,同时还可以看到端口映射的关系,包括从什么image来的,运行什么样的命令等等,上面命令就是要本机的8080端口开启了一个nginx服务。

  现在我在本地准备一个index.html文件,文件内容如下:

<html>
<h1>Docker is fun!</h1>
</html>

  docker cp E:developindex.html b05d0bd5ecab:/usr/share/nginx/html

  这样,Docker容器里面的一个网页已经被我们成功替换了。

  docker stop 容器ID:停止Docker容器。

  这时再用docker run -p 8080:80 -d nginx命令启动,再次访问localhost:8080,不再是“Docker is fun!”。因为Docker在容器内所做的改动都是暂时的,都缺省没有被保存下来的,而要保存需要做一些另外的操作。

  docker commit命令保存了一个改动,实际上是产生了一个新的image。

  docker rmi IMAGE ID:删除image。

  docker stop 容器ID:停止正在运行的image。

  docker ps:显示正在运行的容器

  docker ps -a:列出所有的容器,包括运行过的,虽然我们把它停止了,但是它在系统里还是有一些历史,如希望把这些也去掉,用docker rm 容器ID。

  命令小结:

  docker pull:获取image

  docker build:创建image

  docker images:列出image

  docker run:运行container

  docker ps:列出container

  docker rm:删除container

  docker rmi:删除image

  docker cp:在host和container之间拷贝文件

  docker commit:保存改动为新的image

三.Dockerfile介绍

  通过编写简单的文件自创docker镜像。

1.第一个Dockerfile

FROM alpine:latest
MAINTAINER bijian
CMD echo 'hello docker'

  FROM alpine:latest:要产生的新镜像有一个Base image(基础镜像),alpine是一个专门针对Linux来做的一个极小的环境

  MAINTAINER bijian:这个命令实际上是没有什么特别功效,在共享的时候告诉其他人这个是我写的而已

  CMD echo 'hello docker':运行一个命令,这个就是我们最终运行容器要产生的效果

  docker build -t hello_docker E:developdocker:新产生image。

  -t:就是给它一个标签,标签就是hello_docker,最后给出一个路径名,实际上就是把这个路径下的所有内容都送给Docker Engine,让他来产生一个image。

2.dockerfile实战

  Dockerfile

FROM ubuntu
MAINTAINER bijian
RUN sed -i 's/http://archive.ubuntu.com/ubuntu//http://mirrors.163.com/ubuntu//g' /etc/apt/sources.list RUN apt
-get update RUN apt-get install -y nginx COPY E:developdockerindex.html /var/www/html entrypoint ["/usr/sbin/nginx","-g","daemon off;"] EXPOSE 80

  FROM ubuntu:基础镜像ubuntu

  RUN sed -i 's/http://archive.ubuntu.com/ubuntu//http://mirrors.163.com/ubuntu//g' /etc/apt/sources.list:做一个加速,用sed把/etc/apt/sources.list文件做一个改动,用的是国内的一个镜像,这样会比较快一些

  RUN apt-get update:更新apt-get库
  RUN apt-get install -y nginx:运行apt-get命令,安装nginx,-y参数表示不要问我(提醒我)
  COPY E:developdockerindex.html /var/www/html:拷贝本地一个文件到容器里面去,不同版本ubuntu这个路径是不一样的
  entrypoint ["/usr/sbin/nginx","-g","daemon off;"]:给出一个容器入点,这里是一个数组语法,三个字符串组成的数组,最后会把这个数组展开(用空格把它隔开),当成一个命令行来执行,作用是将nginx在前台执行

  EXPOSE 80:暴露80端口,普通http服务的监听端口

  E:developdockerindex.html内容是:今天是周末!

  用docker build -t bj/hello-nginx E:developdocker命令构建时,一直未成功,如下所示:

  将命令加上--no-cache,即创建镜像的过程不使用缓存后,docker build --no-cache -t bj/hello-nginx E:developdocker,都不成功。

  用加速器:

  不用加速器:

  如果正常将会如下所示:

  运行容器,命令:docker run -d -p 80:80 bj/hello-nginx,其中,-d:守护进程化,-p:把端口暴露出来。

  Dockerfile语法小结:

  FROM:base image

  RUN:执行命令

  ADD:添加文件,还可以将远程服务器上的文件加到容器上去

  COPY:拷贝文件

  CMD:执行命令,通常可用CMD和entrypoint给容器指定一个容器执行的入口

  EXPOSE:暴露端口

  WORKDIR:指定路径,指定我们运行命令的路径

  MAINTAINER:维护者

  ENV:设定环境变量

  ENTRYPOINT:容器入口,和CMD相似都是设定容器入口,当然它和CMD又不一样,在没有指定entrypoint的时候,就用CMD来启动,如果指定了ENTRYPOINT,CMD所指定的字符串就变成了ENTRYPOINT的参数

  USER:指定用户,即执行该命令的用户

  VOLUME:mount point,指定容器所挂载的卷

3.镜像分层

  Dockerfile中的第一行都产生一个新层。

  每一行对应一个层,每一层有一个独立的ID,每一行的Dockerfile都产生一个新层。

  已经存在image里面的层是可读的,一旦一个image被运行成一个容器的话,将会产生一个新层,这层叫做容器层,是可读可写的,这保证我们的容器是可以被改变的。

  分层有什么好处呢?比如我有很多很多image,image A有10层,image B有7层,它们之间可能有5层是共享的,无形中我们的存储压力就小很多。

四.存储

1.volume介绍

  提供独立于容器之外的持久化存储。之前我们看到我们在之前运行容器的时候,在容器中的改动,缺省是不会被保存的,Volume提供了一个方便的、可以持久化存储的技巧,比如我们运行一个数据库操作,数据库的容器,数据库真正的数据应该被持久化的,Volume就可以做这个事情,并且Volume可以提供容器与容器之间共享的数据。

2.volume操作

  a.第一种形式的数据卷

  $docker run -v /usr/share/nginx/html nginx:运行一个nginx容器,通过-v挂载一个卷。

  docker inspect nginx命令来检查一下,它给出了容器很多很多的信息,我们关心如下信息:

  它是把宿主机里的/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径挂载到容器内部的/usr/share/nginx/html地址。但是,在Windows上没有/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径,Mac上也是一样没有,在Mac上还有一层,它是通过一个虚拟层运行了一个主机,在这个主机里运行的Docker,在Mac上可以通过screen就可以进去。

  如果用的是Linux Host的话,就没有这么复杂,直接进入/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径即可,而在Windows10上,我暂时也没有精力去研究它到底如何进的,暂时先不管,先知道就好了。

  接着上面的,如果我们进入/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径下,就可以看到nginx的50x.html、index.html两个文件。echo "it's 2019" > index.html中去,回到Docker容器里面,就会发现内容被修改了。如下命令docker exec -it nginx /bin/bash可以进入容器。

  b.第二种形式的数据卷

   $docker run -v $PWD/code:/var/www/html nginx:本地的一个目录挂载到容器里面的数据卷里面去。

  实例命令:docker run -p 80:80 -d -v E:developdockerhtml:/usr/share/nginx/html nginx,表示将宿主机的E:developdockerhtml目录挂载到/usr/share/nginx/html目录,但是我运行时还是不成功。

  即便我参考https://blog.csdn.net/weixin_35723062/article/details/80989662进行了盘符共享,即进入Docker of windows的Setting 中进行配置,将盘符进行共享。

  点击“Apply”并输入开机密码后依然好像没有共享成功的样子。如果运行成功,修改本机E:developdockerhtml下的index.html内容,访问http://localhost将会看到修改后的内容。

  其实这是一个很好的开发环境,我把本地开发的内容和容器内的服务器结合起来,无需到容器中去改,只需要在Host上改就可以自动的在容器内反应出来。

  c.第三种形式的数据卷

  $docker run --volumes-from ...:创建一个仅有数据的一个容器,并将这个容器当做Volume挂载到其它容器里面去。

 

  但在我本机依然无法正常共享我本地的驱动。如下是学习视频的截图,是在Mac上安装Docker进行的操作。

   上面的命令执行后,产生了一个仅有数据的一个容器,下面我们运行一个新的容器,把上面这个容器数据卷加载到新的容器里面去,--volumes-from表示从另外一个容器挂载,volumes-from data_container表示从上面的容器挂载。而我们要运行一个容器,所以也要给出一个镜像,在这里还是给出ubuntu,而ubuntu本身是一个基础镜像,它本身没有什么服务,所以-it用交互的方式来运行,这样我们会直接进入到我们的容器里面去。

  进入容器后,我们执行mount命令,就可以看到挂载信息。

  在容器里进入到/var/mydata目录,新建whatever.txt,退出容器,也可以看到刚在容器中新建的whatever.txt文件,这说明数据卷的挂载是成功。实际上,这个仅有数据的容器可以被多个容器挂载,做到数据共享。

五.镜像仓库

1.registry介绍

  registry是镜像仓库,目的是为了大家来共享镜像。

a.术语

  host:宿主机,就是我们正在使用的这台电脑。

  image:镜像,是可以从远端拉取或者本地构建的、可以重复使用的软件的打包

  container:容器,它是镜像的运行

  registry:仓库

  daemon:守护程序

  client:客户端,给daemon输命令的,用来操作的

b.常用操作

  $docker search whalesay:从Registry仓库里面搜索一个我想要的一个镜像

  $docker pull whalesay:可以从Registry仓库把镜像pull下来

  $docker push myname/whalesay:可以把我本地制作的镜像push到仓库去

c.国内的一些仓库

  daocloud、时速云、aliyun

  国内加速站点:

  https://registry.docker-cn.com
  http://hub-mirror.c.163.com
  https://3laho3y3.mirror.aliyuncs.com
  http://f1361db2.m.daocloud.io
  http://141e5461.m.daocloud.io

  特别说明:http://141e5461.m.daocloud.io搜索下载不成功,换成https://registry.docker-cn.com后OK。

2.registry实战

  docker search whalesay,搜索到这么多结果,按STARS排序,OFFICIAL表明是否是官方的。

  把镜像拖下来。

  docker images,可以看到刚pull下来的whalesay镜像,REPOSITORY表示镜像名,TAG是标签,同一个镜像可以有很多TAG,比如1.0、2.0、3.0等等,latest是缺省的TAG。

  运行docker/whalesay

  docker tag docker/whalesay bijian/whalesay,制作新的镜像(虽然这里和原来的docker/whalesay是一样的,在这里仅为了演示而已)

  docker push bijian/whalesay:把本地的镜像push到Docker仓库,push成功后,就可以在服务器上看到。

六.多容器app

1.compose介绍

  通过docker-compose工具来拉起一个多容器的应用,在这里是编写一个简单的文本文件,这个文件描述一个多容器app的结构,然后通过docker-compose工具把它拉起来。

  docker-compose安装:Mac/Windows自带,Linux:curl https://github.com/docker/compose...

2.compose-install-linux

  Linux下安装:curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose,$(uname -s)就是把uname -s的命令的输出加在这个地方,形成一个完整的地址。

  用curl -L下载下来,再用管道的方式写到/usr/local/bin/docker-compose文件中。/usr/local/bin通常在我们的路径里面,可以保证我们在任何地方都可以执行compose这个命令。

3.compose实战

  大致三个容器

  先创建相应目录和Dockerfile文件。

  ghost目录下的Dockerfile文件内容如下:

FROM ghost
COPY ./config.js /var/lib/ghost/config.js
EXPOSE 2368
CMD ["npm", "start", "--production"]

  config.js内容如下:

var path = require('path'),
config;

config = {
    production: {
        url: 'http://mytestblog.com',
        mail: {},
        database: {
            client: 'mysql',
            connection: {
                host: 'db',
                user: 'ghost',
                password: 'ghost',
                database: 'ghost',
                port: '3306',
                charset: 'utf8'
            },
            debug: false
        },
        paths: {
            contentPath: path.join(process.env.GHOST_CONTENT, '/')
        },
        server: {
            host: '0.0.0.0',
            port: '2368'
        }
    }
};

module.exports = config;

  进入到nginx目录,再创建Dockerfile文件,内容如下:

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80

  在此目录下新建nginx.conf内容如下:

worker_processes 4;
events {worker_connections 1024;}
http {
    server {
        listen 80;
        location / {
            proxy_pass http://ghost-app:2368;
        }
    }
}

  最后在nginx、ghost、data同级的目录下新建docker-compose.yml文件,内容如下:

version: '2'

networks:
    ghost:
services:
    ghost-app:
        build: ghost
        networks:
            - ghost
        depends_on:
            - db
        ports:
            - "2368:2368"
            
    nginx:
        build: nginx
        networks:
            - ghost
        depends_on:
            - ghost-app
        ports:
            - "80:80"

    db:
        image: "mysql:5.7.15"
        networks:
            - ghost
        environment:
            MYSQL_ROOT_PASSWORD: mysqlroot
            MYSQL_USER: ghost
            MYSQL_PASSWORD: ghost
        volumes:
            - ./data:/var/lib/mysql
        ports:
            - "3306:3306"

  yml文件是yaml语法,它是现在比较常用的配置文件的格式,是通过缩进的方式来表达层级关系,比如这个文件有三个顶层的对象ghost-app、nginx、db对应上面的三个服务,每个服务有各自的描述,如ghost-app依赖db,有端口映射关系。

  我们这里共创建了三个目录,ghost、nginx是用来存放Dockerfile和配置文件,用来构建镜像的,data本身是用来存放博客需要的数据,compose是用名字把各个服务联系起来,自已会把名字解析。

  经过上面的准备工作,可以把整个系统拉起来,命令:docker-compose up -d。

  可以用docker-compose stop把它停掉,docker-compose rm可以把停掉的各个容器删掉,如果有修改配置文件需要重新构建,命令:docker-compose build,再用docker-compose up -d命令拉起来。

  最终还是没能正常启动,学习视频是正常启动运行的。

  依次创建了db、ghost、nginx,表示已经起来了,在浏览器中输入http://localhost,显示如下:

  输入localhost/ghost可以用来做配置,配置好后写一个博客,再进入http://localhost即可看到刚发布的博客。

  docker-compose.yml常用命令:

  build:本地创建镜像

  command:覆盖缺省命令

  depends_on:连接容器

  ports:暴露端口

  volumes:卷

  image:pull镜像

  docker-compose命令:

  up:启动服务

  stop:停止服务

  rm:删除服务中的各个容器

  logs:观察各个容器的日志

  ps:列出服务相关的容器

  

七.小结

  Docker介绍、如何制作镜像、如何分享镜像、如何持久化容器数据、如何编排一个多容器的应用

学习地址:https://www.imooc.com/learn/867

参考文章:https://blog.csdn.net/weixin_35723062/article/details/80989662https://blog.csdn.net/ldzm_edu/article/details/78251528

原文地址:https://www.cnblogs.com/flyingeagle/p/10354166.html