Category Archives: Docker

探索Docker Compose

寸有所长,尺有所短

单机单容器,docker够用
单机多容器,要docker compose
多机多容器,上K8S

为什么要有Docker Compose多容器部署?为了多快好省,总结起来就是为了偷懒

在使用 docker Compose之前,我们是怎么部署多个容器的APP应用的呢???
要从Dockerfile build image 或者 Dockerhub 拉取image
要创建多个container
要管理这些container(启动停止删除)
多容器部署的APP太恶心了(每次都这么多步骤)

docker Compose到底是什么
docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具
可使用 YAML 配置应用程序的服务
使用一个命令,可从配置中创建并启动所有服务

docker Compose 适用于所有环境:生产、暂存、开发、测试及 CI 工作流。还具有用于管理应用程序整个生命周期的命令:
启动、停止和重建服务
查看运行服务的状态
流式传输正在运行的服务的日志输出
在服务上运行一次性命令

docker yml 文件有一个默认在名字叫docker-compose.yml,其中有三个重要的概念:
Services
Networks
Volumes

Services
一个Services代表一个container,这个container可以从dockerhub registory的image来创建,或者从本地的Dockerfile build 出来的image来创建
Service的启动类似docker run,我们可以给其指定network和volume,所以可以给service指定network和Volume的引用

安装Docker Compose

// 安装dockers compose
apt install docker-compose
// 查看版本检查是否安装成功
docker-compose -v

在当前目录下创建YML文件

nano ng.yml

输入以下内容:

version: '3'
services:
  web:
    # 对象键值对冒号后要跟一个空格
    image: nginx
    ports:
      - 9998:80

使用docker compose 启动容器

root@debian:~# docker-compose -f ng.yml up -d
Creating network "root_default" with the default driver
Creating root_web_1 ... done

使用浏览器加上端口就可以访问。

关闭容器

root@debian:~# docker-compose -f ng.yml stop
Stopping root_web_1 ... done

其他命令

docker-compose up -d    #以后台方式启动运行
docker-compose ps   # 查看启动的服务App
docker-compose up --help
docker-compose down  #关闭删除
docker-compose build    #

其他:
如果把刚刚的ng.yml名称改为docker-compose.yml
可以直接用命令docker-compose up -d 启动容器。上面的-f参数是指定yml文件名称。

root@debian:~# ls
docker  docker-compose.yml
root@debian:~# docker-compose up -d
Creating network "root_default" with the default driver
Creating root_web_1 ... done
root@debian:~# docker-compose down
Stopping root_web_1 ... done
Removing root_web_1 ... done
Removing network root_default

命令使用说明

build 构建(重新构建)项目中的服务容器
config 检测 compose 文件的错误
up 启动服务
down 停止容器
images 列出项目中所包含的镜像
logs 查看服务容器的日志
kill 发送 SIGKILL 信号来强制停止服务容器
port 查看某个容器端口所映射的公共端口
ps 列出项目中目前的所有容器
restart 重启项目中的服务
rm 删除所有停止状态的服务容器
run 在指定服务上运行一个命令
scale 设置指定服务运行的容器个数
stop 停止处于运行状态的容器
start 启动被 stop 的服务容器
top 查看各个服务容器内运行的进程
pause 暂停一个服务容器
unpause 恢复处于暂停状态中的服务
docker-compose 术语:

服务(service):一个应用容器,实际上可以运行多个相同镜像的实例。
项目(project):由一组关联的应用容器组成的一个完整业务单元。
一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

探索Docker 卷

你必须知道的Docker数据卷(Volume)

一、将Docker数据挂载到容器
在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:

(1)volumes:Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)
所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。

(2)bind mounts:意为着可以存储在宿主机系统的任意位置;(比较常用的方式)
但是,bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。

(3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统;(一般都不会用的方式)

二、Volume的基本使用
2.1管理卷

// 创建一个自定义容器卷
docker volume create edc-nginx-vol

// 查看所有容器卷
docker volume ls

// 查看指定容器卷详情信息
docker volume inspect edc-nginx-vol

输出如下:

root@debian:~# docker volume create edc-nginx-vol
edc-nginx-vol
root@debian:~# docker volume ls
DRIVER    VOLUME NAME
local     88c39923317234d00b26d9ed1aef542423bfe61787344acadd8f35b0884d45e3
local     edc-nginx-vol
local     root_data
local     x_data
root@debian:~# docker volume inspect edc-nginx-vol
[
    {
        "CreatedAt": "2024-10-31T21:12:04+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/edc-nginx-vol/_data",
        "Name": "edc-nginx-vol",
        "Options": {},
        "Scope": "local"
    }
]

2.2创建使用指定卷的容器
有了自定义容器卷,我们可以创建一个使用这个数据卷的容器,这里我们以nginx为例:

docker run -d -it --name=edc-nginx -p 8800:80 -v edc-nginx-vol:/usr/share/nginx/html nginx

其中,-v代表挂载数据卷,这里使用自定数据卷edc-nginx-vol,并且将数据卷挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。如果没有通过-v指定,那么Docker会默认帮我们创建匿名数据卷进行映射和挂载。

创建好容器之后,我们可以进入容器里面看看:

root@debian:~# docker run -d -it --name=edc-nginx -p 8800:80 -v edc-nginx-vol:/usr/share/nginx/html nginx
d067ff1b256163fcbab2779a944d47603c7346a2b451af792d95bcb85bab97dd
root@debian:~# docker exec -it edc-nginx bash
root@d067ff1b2561:/# cd /usr/share/nginx/html
root@d067ff1b2561:/usr/share/nginx/html# ls
50x.html  index.html

可以看到有两个默认页,这时我们新启动一个SSH连接到宿主机去到刚刚创建的数据卷里边看看:

root@debian:~# cd /var/lib/docker/volumes/edc-nginx-vol/_data
root@debian:/var/lib/docker/volumes/edc-nginx-vol/_data# ls
50x.html  index.html

可以看到,我们可以访问到容器里面的两个默认页面,由此可知,volume帮我们做的类似于一个软链接的功能。在容器里边的改动,我们可以在宿主机里感知,而在宿主机里面的改动,在容器里边可以感知到。

这时,如果我们手动stop并且remove当前nginx容器,我们会发现容器卷里面的文件还在,并没有被删除掉。

root@debian:/var/lib/docker/volumes/edc-nginx-vol/_data# docker stop edc-nginx
edc-nginx
root@debian:/var/lib/docker/volumes/edc-nginx-vol/_data# docker rm edc-nginx
edc-nginx
root@debian:/var/lib/docker/volumes/edc-nginx-vol/_data# ls
50x.html  index.html

由此可以验证,在数据卷里边的东西是可以持久化的。如果下次还需要创建一个nginx容器,那么还是复用当前数据卷里面的文件。
此外,我们还可以启动多个nginx容器实例,并且共享同一个数据卷,复用性和扩展性较强。

2.3清理卷
如果不再使用自定义数据卷了,那么可以手动清理掉:

// 暂停容器实例
docker stop edc-nginx

// 移除容器实例
docker rm edc-nginx

// 删除自定义数据卷
docker volume rm edc-nginx-vol
root@debian:~# docker stop edc-nginx
// 前面已经停止过容器
Error response from daemon: No such container: edc-nginx
root@debian:~# docker rm edc-nginx
// 前面已经删除过容器
Error: No such container: edc-nginx
root@debian:~# docker volume rm edc-nginx-vol
// 成功删除卷
edc-nginx-vol

三、Bind Mounts的基本使用

3.1使用卷创建一个容器

docker run -d -it --name=edc-nginx -v /app/wwwroot:/usr/share/nginx/html nginx

这里指定了将宿主机上的 /app/wwwroot 目录(如果没有会自动创建)挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。
这时我们再次进入容器内部看看:

root@debian:~# docker exec -it edc-nginx bash
root@12bbb8b84b25:/# cd /usr/share/nginx/html
root@12bbb8b84b25:/usr/share/nginx/html# ls
root@12bbb8b84b25:/usr/share/nginx/html#

可以看到,与volumes不同,bind mounts的方式会隐藏掉被挂载目录里面的内容(如果非空的话),这里是/usr/share/nginx/html 目录下的内容被隐藏掉了,因此我们看不到。

但是,我们可以将宿主机上的文件随时挂载到容器中:
Step1.新建一个index.html

root@debian:~# ls /
app  boot  etc   initrd.img      lib    lost+found  mnt  proc  run   srv  tmp  var      vmlinuz.old
bin  dev   home  initrd.img.old  lib64  media       opt  root  sbin  sys  usr  vmlinuz
root@debian:~# cd /app/wwwroot
root@debian:/app/wwwroot# nano index.html
root@debian:/app/wwwroot# ls
index.html

Step2.在容器中查看

root@12bbb8b84b25:/usr/share/nginx/html# ls
index.html

3.2验证绑定

docker inspect edc-nginx

通过上述命令可以看到一大波配置,我们要关注的是:

        "HostConfig": {
            "Binds": [
                "/app/wwwroot:/usr/share/nginx/html"
            ],
            "ContainerIDFile": "",

3.3清理

同volumes一样,当我们清理掉容器之后,挂载目录里面的文件仍然还在,不会随着容器的结束而消失,从而实现数据持久化。

3.4应用案例
在服务治理组件中,服务发现组件是一个最常用的组件之一,Consul是一个流行的服务发现开源项目,Consul推荐我们使用配置文件的方式注册服务信息。因此,我们常常会将填写好服务注册配置文件放在宿主机的一个文件目录下将其挂载到Consul的容器指定目录下,如下所示:

docker run -d -p 8500:8500 --restart=always \
    -v /app/data:/consul/data \
    -v /app/conf:/consul/config \
    -e CONSUL_BIND_INTERFACE='eth0' \
    --privileged=true \
    --name=consul_server_1 consul:1.4.4 agent -server -bootstrap-expect=3 -ui -node=consul_server_1 -client='0.0.0.0' \
    -data-dir /consul/data \
    -config-dir /consul/config \
    -datacenter=xdp_dc;

可以看到,我们通过Bind Mounts的方式将宿主机上的/XiLife/consul/data/server1目录挂载到了容器的/consul/data目录下,还将/XiLife/consul/conf/server1目录挂载到了容器的/consul/config目录下,而容器下的两个目录/consul/data和/consul/config则是我们指定的存放agent数据和配置文件的地方。因此,宿主机上的配置文件的变化会及时反映到容器中,比如我们在宿主机上的目录下更新了配置文件,那么只需要reload一下Consul的容器实例即可:

oot@debian:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                                                         NAMES
3fb3675de102   consul:1.4.4   "docker-entrypoint.s…"   57 seconds ago   Up 56 seconds   8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:8500->8500/tcp, :::8500->8500/tcp   consul_server_1
root@debian:~# docker exec consul_server_1  consul reload
Configuration reload triggered

*.这里的consul-server是容器的名字,consul reload是重新加载的命令(非restart)。

四、小结

本文探索了Docker的数据卷及挂载数据到容器的两种主要方式Volumes和Bind Mounts,并介绍基本的使用方式和步骤,通过数据卷我们可以实现Docker的数据持久化,在实际应用中比较广泛。

YAML 入门教程

YAML 入门教程

YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。

YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。

YAML 的配置文件后缀为 .yml,如:runoob.yml 。

基本语法

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释
  • 数据类型
    YAML 支持以下几种数据类型:

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  • 纯量(scalars):单个的、不可再分的值
  • YAML 对象
    对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格。
    也可以使用 key:{key1: value1, key2: value2, ...}。
    还可以使用缩进表示层级关系;

    key: 
        child-key: value
        child-key2: value2
    

    较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的 key,配合一个冒号加一个空格代表一个 value:

    ?  
        - complexkey1
        - complexkey2
    :
        - complexvalue1
        - complexvalue2
    

    意思即对象的属性是一个数组 [complexkey1,complexkey2],对应的值也是一个数组 [complexvalue1,complexvalue2]

    YAML 数组
    以 - 开头的行表示构成一个数组:

    - A
    - B
    - C
    

    YAML 支持多维数组,可以使用行内表示:

    key: [value1, value2, ...]
    数据结构的子成员是一个数组,则可以在该项下面缩进一个空格。

    -
     - A
     - B
     - C
    

    一个相对复杂的例子:

    companies:
        -
            id: 1
            name: company1
            price: 200W
        -
            id: 2
            name: company2
            price: 500W
    

    意思是 companies 属性是一个数组,每一个数组元素又是由 id、name、price 三个属性构成。

    数组也可以使用流式(flow)的方式表示:

    companies: [{id: 1,name: company1,price: 200W},{id: 2,name: company2,price: 500W}]
    

    复合结构

    数组和对象可以构成复合结构,例:

    languages:
      - Ruby
      - Perl
      - Python 
    websites:
      YAML: yaml.org 
      Ruby: ruby-lang.org 
      Python: python.org 
      Perl: use.perl.org
    

    转换为 json 为:

    { 
      languages: [ 'Ruby', 'Perl', 'Python'],
      websites: {
        YAML: 'yaml.org',
        Ruby: 'ruby-lang.org',
        Python: 'python.org',
        Perl: 'use.perl.org' 
      } 
    }
    

    纯量
    纯量是最基本的,不可再分的值,包括:

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期
  • 使用一个例子来快速了解纯量的基本使用:

    boolean: 
        - TRUE  #true,True都可以
        - FALSE  #false,False都可以
    float:
        - 3.14
        - 6.8523015e+5  #可以使用科学计数法
    int:
        - 123
        - 0b1010_0111_0100_1010_1110    #二进制表示
    null:
        nodeName: 'node'
        parent: ~  #使用~表示null
    string:
        - 哈哈
        - 'Hello world'  #可以使用双引号或者单引号包裹特殊字符
        - newline
          newline2    #字符串可以拆成多行,每一行会被转化成一个空格
    date:
        - 2018-02-17    #日期必须使用ISO 8601格式,即yyyy-MM-dd
    datetime: 
        -  2018-02-17T15:02:31+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
    

    引用
    & 锚点和 * 别名,可以用来引用:

    defaults: &defaults
      adapter:  postgres
      host:     localhost
    
    development:
      database: myapp_development
      <<: *defaults
    
    test:
      database: myapp_test
      <<: *defaults
    

    相当于:

    defaults:
      adapter:  postgres
      host:     localhost
    
    development:
      database: myapp_development
      adapter:  postgres
      host:     localhost
    
    test:
      database: myapp_test
      adapter:  postgres
      host:     localhost
    

    &用来建立锚点(defaults),<< 表示合并到当前数据,* 用来引用锚点。

    下面是另一个例子:

    - &showell Steve 
    - Clark 
    - Brian 
    - Oren 
    - *showell 
    

    转为 JavaScript 代码如下:

    [ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]
    

    参考地址:

    https://www.ruanyifeng.com/blog/2016/07/yaml.html
    https://www.jianshu.com/p/97222440cd08
    https://daihainidewo.github.io/blog/yaml%E6%95%99%E7%A8%8B/

    在 Docker 中安装 MariaDB

    在 Docker 中安装 MariaDB
    1.拉取 MariaDB 镜像:

    docker pull mariadb

    2.运行 MariaDB 容器:

    docker run -d -p 3306:3306 --name mymariadb -e MYSQL_ROOT_PASSWORD=your_password mariadb

    请将 your_password 替换为您设置的 MariaDB root 密码。

    3.确认 MariaDB 容器正在运行:

    docker ps

    现在您已经在 Docker 中成功安装了MariaDB。可以使用MySQL客户端连接到MariaDB数据库。

    安装phpmyadmin
    web管理工具phpmyadmin

    docker run --name phpmyadmin-5080 -d -e PMA_ARBITRARY=1 -p 5080:80 phpmyadmin

    在浏览器中输入http://docker_ip:5080
    在phpmyadmin中输入docker主机的ip地址,Mariadb的账号密码,就可以使用phpmyadmin管理了。

    Docker配置nginx

    Docker配置nginx

    本文详细介绍了如何在Docker中安装和配置Nginx,包括安装命令、查看容器、运行测试、文件映射以及Nginx服务的配置和部署。重点讨论了文件映射的重要性,以便于在主机上直接编辑Nginx配置和管理文件。此外,还讲解了正向代理和反向代理的概念,并给出了反向代理的配置示例,展示了如何通过Nginx代理访问不同域名的服务。

    Docker安装nginx

    docker search nginx
    docker pull nginx
    

    查看是否安装

    docker images
    

    root@debian:~# docker pull nginx
    Using default tag: latest
    latest: Pulling from library/nginx
    a480a496ba95: Pull complete
    f3ace1b8ce45: Pull complete
    11d6fdd0e8a7: Pull complete
    f1091da6fd5c: Pull complete
    40eea07b53d8: Pull complete
    6476794e50f4: Pull complete
    70850b3ec6b2: Pull complete
    Digest: sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb
    Status: Downloaded newer image for nginx:latest
    docker.io/library/nginx:latest
    root@debian:~# docker images
    REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
    nginx        latest    3b25b682ea82   3 weeks ago   192MB
    

    运行测试nginx

    docker run --name nginx-test -p 9091:80 -d nginx
    

    --name #给你启动的容器起个名字,以后可以使用这个名字启动或者停止容器
    -p #映射端口,将docker宿主机的9091端口和容器的80端口进行绑定
    -v #挂载文件用的
    -d #表示启动的是哪个镜像。

    测试是否启动成功

    root@debian:~# wget <a href="http://localhost:9091">http://localhost:9091</a>
    --2024-10-29 20:43:28--  <a href="http://localhost:9091/">http://localhost:9091/</a>
    Resolving localhost (localhost)... ::1, 127.0.0.1
    Connecting to localhost (localhost)|::1|:9091... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 615 [text language=&quot;/html&quot;][/text]
    Saving to: ‘index.html’
    index.html                                 100%[======================================================================================&gt;]     615  --.-KB/s    in 0s
    2024-10-29 20:43:28 (135 MB/s) - ‘index.html’ saved [615/615]
    

    Nginx服务的配置和部署

    为什么需要做文件的映射?
    我们在使用容器的过程中需,有时候需要对容器中的文件进行修改管理,如果不做文件映射的化,我们使用docker exec -it 容器ID/容器名 /bin/bash 才能进入nginx中的文件里面。

    docker exec -it nginx-test /bin/bash
    

    root@debian:~# docker exec -it nginxtest /bin/bash
    Error: No such container: nginxtest
    root@debian:~# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
    ee033e7b4b95   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:9091->80/tcp, :::9091->80/tcp   nginx-test
    root@debian:~# docker exec -it nginx-test /bin/bash
    root@ee033e7b4b95:/# ls
    bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    root@ee033e7b4b95:/# cd /etc/nginx
    root@ee033e7b4b95:/etc/nginx# ls
    conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params
    root@ee033e7b4b95:/etc/nginx# cd conf.d
    root@ee033e7b4b95:/etc/nginx/conf.d# ls
    default.conf
    

    如果把关键文件映射到主机上,那么就可以在主机中进行修改而不必进入文件当中才进行修改了。

    需要在主机上建立相应的关键文件目录

    • 在home下创建一个docker文件夹,用来专门存docker容器的映射文件。
    • 在docker下创建一个nginx的文件夹,用于存nginx的映射文件。
    • 在nginx下创建三个关键的映射文件。
    • www文件映射www目录,也就是网页目录。
    • logs文件映射日志目录。
    • conf文件映射配置目录

    root@debian:~# mkdir docker && cd docker && mkdir nginx && cd nginx
    root@debian:~/docker/nginx# mkdir www logs conf
    root@debian:~/docker/nginx# ls
    conf  logs  www
    root@debian:~/docker/nginx#
    

    先在容器中拷贝配置文件

    docker cp 容器ID:/etc/nginx/nginx.conf /home/docker/nginx/conf
    

    注意此时的容器必须是运行的

    root@debian:~/docker/nginx# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
    ee033e7b4b95   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:9091->80/tcp, :::9091->80/tcp   nginx-test
    root@debian:~/docker/nginx# docker cp ee033e7b4b95:/etc/nginx/nginx.conf /root/docker/nginx/conf
    

    docker中nginx与主机文件映射规则如下

    主机
    docker

    /root/docker/nginx/www
    /usr/share/nginx/html #网页文件

    /root/docker/nginx/conf/nginx.conf
    /etc/nginx/nginx.conf#配置文件

    /root/docker/nginx/logs
    /var/log/nginx#日志文件

    root@debian:~/docker/nginx# docker cp ee033e7b4b95:/usr/share/nginx/html /root/docker/nginx/www
    root@debian:~/docker/nginx# docker cp ee033e7b4b95:/var/log/nginx /root/docker/nginx/logs
    

    关闭之前运行的容器并删除容器
    docker stop 容器ID
    docker rm 容器ID

    root@debian:~/docker/nginx# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
    ee033e7b4b95   nginx     "/docker-entrypoint.…"   16 minutes ago   Up 16 minutes   0.0.0.0:9091->80/tcp, :::9091->80/tcp   nginx-test
    root@debian:~/docker/nginx# docker stop ee033e7b4b95 && docker rm ee033e7b4b95
    ee033e7b4b95
    ee033e7b4b95
    

    运行nginx,同时进行文件挂载

    docker run -d -p 9091:80  --name nginx-test -v /root/docker/nginx/www:/usr/share/nginx/html -v /root/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /root/docker/nginx/logs:/var/log/nginx nginx
    

    root@debian:~/docker/nginx# docker run -d -p 9091:80  --name nginx-test -v /root/docker/nginx/www:/usr/share/nginx/html -v /root/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /root/docker/nginx/logs:/var/log/nginx nginx
    6d381d523815ff37c4a59fed1696fbc74af35cdf767ba532f3c3d42881403188
    

    测试以下

    root@debian:~/docker/nginx# wget <a href="http://localhost:9091">http://localhost:9091</a>
    --2024-10-29 21:00:15--  <a href="http://localhost:9091/">http://localhost:9091/</a>
    Resolving localhost (localhost)... ::1, 127.0.0.1
    Connecting to localhost (localhost)|::1|:9091... connected.
    HTTP request sent, awaiting response... 403 Forbidden
    2024-10-29 21:00:15 ERROR 403: Forbidden.
    

    返回403错误,nginx的http服务已开通,但是服务器上没有开目录浏览或者没有index.html文件。

    在www目录下建立一个html文件

    echo "it works,nginx is runing" > /root/docker/nginx/www/index.html
    

    测试一下

    root@debian:~# wget <a href="http://localhost:9091">http://localhost:9091</a>
    --2024-10-29 21:09:48--  <a href="http://localhost:9091/">http://localhost:9091/</a>
    Resolving localhost (localhost)... ::1, 127.0.0.1
    Connecting to localhost (localhost)|::1|:9091... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 25 [text language=&quot;/html&quot;][/text]
    Saving to: ‘index.html’
    index.html                                 100%[======================================================================================&gt;]      25  --.-KB/s    in 0s
    2024-10-29 21:09:48 (6.35 MB/s) - ‘index.html’ saved [25/25]
    root@debian:~# cat index.html
    it works,nginx is runing
    

    nginx返回了一个index.html文件保存在当前文件夹,使用cat查看文件内容,即显示it works,nginx is runing
    可以在浏览器中输入网址http://ip:9091, ip换成DOCKER主机的IP地址, 显示一样的内容。

    Nginx的普通配置

    通过nginx为多为个域名配置服务,使得通过浏览器可以访问到相应的域名。

    创建html文件
    在映射到主机下的/root/docker/nginx/www下创建html文件或者域名的文件夹

    root@debian:~/docker/nginx/www# mkdir www.abc.com www.dba.com
    root@debian:~/docker/nginx/www# ls
    www.abc.com
    root@debian:~/docker/nginx/www#
    

    其中www.abc.com和www.dba.com是存放不同域名访问的文件路径。里面都有对应的index.html

    修改host文件
    在DNS中做了域名解析的话不需要修改host文件,这里纯粹是测试。

    127.0.0.1       localhost
    127.0.1.1       debian
    127.0.0.1 www.abc.com
    127.0.0.1 www.dba.com
    

    NANO可以使用键盘的删除、退格、下一行等功能键。修改完按CTRL_O再按回车键保存,按CTRL+X推出NANO。
    测试一下

    root@debian:~/docker/nginx/www# ping www.abc.com
    PING www.abc.com (127.0.0.1) 56(84) bytes of data.
    64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.042 ms
    64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.039 ms
    ...
    

    修改nginx.conf文件

    提醒「路径问题」
    这里需要提醒一下,在前面我们已经把nginx中的配置文件映射到主机目录下,我们在主机目录下修改了/root/docker/nginx/www的文件,同时nginx容器中的/usr/share/nginx/html下的文件有会有相同的变化。但是在配置文件中使用的路径得是nginx的,而不应该是主机的路径。

    打开主机映射的nginx配置文件

    root@debian:~# nano /root/docker/nginx/conf/nginx.conf
    

    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
        sendfile        on;
        #tcp_nopush     on;
        keepalive_timeout  65;
        #gzip  on;
        include /etc/nginx/conf.d/*.conf;
    
        # 配置服务www.abc.com
        server{
            #监听端口
            listen 80;
            #配置域名
            server_name www.abc.com;
            #配置网站跟目录
            root /usr/share/nginx/html/www.abc.com;
            location / {
                    #跟目录
                    root /usr/share/nginx/html/www.abc.com;
                    #默认首页
                    index index.html index.htm;
                }  
            }
    }

    重启docker容器
    docker ps#获取容器的ID
    docker restart 容器ID

    root@debian:~# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
    201da9573fce   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:9091->80/tcp, :::9091->80/tcp   nginx-test
    root@debian:~# docker restart 201da9573fce
    201da9573fce

    测试一下

    root@debian:~# wget http://www.abc.com:9091
    --2024-10-29 22:23:44--  http://www.abc.com:9091/
    Resolving www.abc.com (www.abc.com)... 127.0.0.1
    Connecting to www.abc.com (www.abc.com)|127.0.0.1|:9091... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 12 
    Saving to: ‘index.html’
    
    index.html                                 100%[======================================================================================>]      12  --.-KB/s    in 0s
    
    2024-10-29 22:23:44 (3.05 MB/s) - ‘index.html’ saved [12/12]

    注意:
    我们启动nginx容器时,用的一直是把容器的80端口映射到主机的9091端口,在配置WWW.ABC.COM时用的80端口,在docker宿主机上访问时也要加上9091端口。

    以同样的方式配置其他域名
    「修改nginx.conf」–「添加一个server」–「重启docker」–「浏览器域名访问测试」

    错误心得
    当有时启动容器,通过docker ps 发现容器并没有启动,那么通过docker ps -a可查看容器的状态:
    created(已创建)
    restarting(重启中)
    running(运行中)
    removing(迁移中)
    paused(暂停)
    exited(停止)
    dead(死亡)
    然后通过查看日志:docker logs 容器ID
    可以从中发现未能启动的原因。

    代理模式

    正向代理
    客户端<---->代理服务器<---->服务器
    架设在客户机与目标主机之间,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将原本要直接发送到web服务器上的http请求发送到代理服务器中。

    反向代理
    客户端—>代理服务器<—>服务器
    反向代理服务器架设在服务端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。正式反向代理对真正的服务器起到了保护作用,所以反向代理比较流行。

    配置反向代理

    通过访问www.dba.com,来访问www.yini.org

    在nginx的配置当中,新增一段server,
    在location中添加proxy_pass http://www.yini.org/

    
        server{
            #监听端口
            listen 80;
            #配置域名
            server_name www.abc.com;
            #配置网站跟目录
            root /usr/share/nginx/html/www.abc.com;
            location / {
                    #跟目录
                    root /usr/share/nginx/html/www.abc.com;
                    #默认首页
                    index index.html index.htm;
    
                }
            }
    
       server {
            listen 80;
            server_name www.dba.com;
    
            location / {
            proxy_pass http://www.yini.org;
            #proxy_set_header Host $host;
            #proxy_set_header X-Real-IP $remote_addr;
            #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #proxy_set_header X-Forwarded-Proto $scheme;
                 }
            }

    Docker系列学习文章 – 什么是docker?(二)

    | 导语 前面我们介绍了什么是容器,那么这篇文章我们继续跟大家讲解什么是docker。 docker是目前最火的LXC高级容器引擎,docker到现在几乎是容器的代名词了,所以学习容器从docker入手是非常正确的!

    一、docker的介绍

    docker由来。

    2010年dotCloud公司在旧金山成立,PAAS平台的服务供应商;2013年dotCloud更名为Docker股份有限公司(Docker,Inc)。Docker公司专注开源容器引擎的开发,他们的容器引擎产品就叫docker,基于go语言,并遵从Apache2.0协议。

    上一篇文章我们跟大家介绍了什么是容器技术,容器技术的底层支持其实就是Linux Container(LXC)技术,LXC技术在 linux 2.6 的 kernel 里就已经存在了,但是LXC设计之初并非为专门为PAAS云计算考虑的,所以LXC缺少一些标准化的管理手段,那时候LXC想用好非常费劲。于是,docker发现了这点,然后针对LXC做了上层标准管理方面的支持,让LXC更加好用。

    那么为什么dotCloud公司能发现这个机遇搞出个docker然后声名大噪呢?就像为什么马云能在中国、在合适的时间创立了阿里巴巴,做了中国首富... 其实,这都是时代的造就。我们深入分析IT架构的发展变革史就能明白一些东西了。

    早期,我们IT行业要成功开发出一个产品,那么要关心的的东西太多了。机房选址、服务器硬件、网络设备、布线、上架、装系统、搭环境、开发、测试... 只要是跟IT相关的你都得去关心安排好。这个时期是传统IT管理与建设的初期,IT资源成本很高,涉及的人才成本也高。

    云计算IAAS时代,AWS、腾讯云、阿里云的出现解决了早期传统IT管理的痛苦,用户有了云将不再面对硬件底层管理的问题,开发和测试都是在云主机上操作。然而,云主机就是一个个不一样的操作系统,硬件底层管理问题没有了,但是中间件相关的问题依然存在!IT运维人员要为开发测试人员提供完善的、稳定的云主机环境,这个过程也是相对复杂的,因为开发测试人员要求的环境也是多种多样,IT运维人员需要花费一定的时间和精力去维护和完善。当前大部分公司还是处在这个阶段。

    容器PAAS时代,这个时代即将到来!(其实,已经来了)。容器技术的出现就是为了解决上面两个时期遗留的痛点问题。有了容器技术,开发者更加专注于程序的开发和测试,开发结束后能快速方便的把开发好的APP迁移到另外一个容器环境里。简单来说,开发人员只需为应用创建一次运行环境,就可以在任何环境里运行;Build Once, Run Anywhere。对于IT运维人员来说,也是好事!再也不用苦逼的为开发人员搞一套又一套不一样的开发环境了,搞出一套PAAS平台,随便让开发使,他们再怎么折腾也不会改变底层的东西,所以不用花大力气去维护这些环境;Configure Once, Run Anything。

    既然这个容器PAAS这么牛逼,那么想做的人也是非常多,docker公司之所以能占领先机搞定,主要是因为它在这领域有一定的积累,之前也跟CoreOS合作过(CoreOS也是做容器技术方面很牛的公司,后来跟docker分道扬镳,Rocket是CoreOS发布的跟docker竞争的产品)。所以,在云计算PAAS风口上,docker在合适的时间通过自己的技术积累发布了这套开源容器管理引擎,想不出名也难了!

    二、 docker的组成架构

    docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后个标准化组件是用户的app)。

    要实现这样的集装箱货轮海运的功能,那么docker是如何去设计如何区做的呢?我们先从docker的架构说起。

    docker主要由以下模块组成:

    Docker 客户端 - Client
    Docker 服务器 - Docker daemon
    Docker 镜像 - Image
    Docker 仓库 - Registry
    Docker 容器 - Container

    Docker 采用的是 (C/S) 架构模式,使用远程REST API来管理和创建Docker容器。既然是采用REST模式,所以客户端和服务端可以不用在一个host上,可以分布式管理部署。

    Docker 客户端 - Client

    docker的客户端分命令和API两种类型。docker 的命令一般在系统安装好docker包后就可以使用,linux下直接是docker开头,可以用docker --help命令查看所有能运行的命令。docker的命令也非常好记,跟linux命令一样,用多了自然就会了;而且学习docker最好的也是从命令入手。

    docker的API一般是写脚本或者开发的时候用比较多,而且都是REST风格的,用命令交互的话可以结合CURL使用。用API能做创建、删除、修改、查询等一系列操作,不过还得结合编程语言使用才会比较强大。

    Docker 服务器 - Docker daemon

    docker daemon就是docker的主服务,docker.service。在linux操作系统下,安装好了docker服务我们就可以使用systemctl start/status/stop docker.service去操作docker的服务。这个服务非常重要,如果你系统的docker.service存在异常,那么你的所有docker关联的组件都会出错。

    Docker 镜像 - Image

    docker的镜像这个很容易理解,如果你玩过vmware或者openstack的话就很容易懂了,vmware和openstack都有镜像模版的概念,我们要衍生创建虚拟机,就可以通过镜像模版来快速部署和生成相同类型的VM。docker的image也是一个道理,通过不同类型的模版,比如redis镜像、nginx镜像来快速创建出容器。好比复制克隆,只要资源够,想生成多少就多少。生成出新的容器你可以使用,然后到时候你又可以打包成镜像。有了镜像这个功能,为生产提供了很好的打包、迭代、传递方式。

    Docker 仓库 - Registry

    Registry就是仓库的意思,我们上面提到docker有镜像,那么镜像会因为业务的需要以不同类型的方式存在。所以,这么多类型的镜像如果没有一个很好的机制去管理,那么肯定会乱套。好比一生产车间,生产需要各种各样的螺丝钉、齿轮等配件,如果没有一个很好的仓库管理员负责对配件进行管理,那么车间里将乱七八糟。同样的,docker 镜像也需要标准化管理,那么负责这块功能的模块就是Registry。不过,要注意的是Registry分共有和私有两种。Docker Hub(https://hub.docker.com/) 是默认的 Registry,由 Docker 公司自己维护,上面有数以万计的镜像,用户可以自由下载和使用。 不过,使用公有镜像速度会很慢(加上GFW的原因),一般公司内部使用docker的话都得搭建私有仓库,不然很影响效率。

    Docker 容器 - Container

    Container就是容器实例了,类比KVM生成的虚拟机。Container是运行时状态,我们可以通过docker命令和API去控制和改变Container的状态,比如start、stop等等。上面所讲的client、daemon、image 和registry都是为了Container的运行稳定而服务的。

    总结:上面通过两点给大家介绍了什么是docker。我想云计算发展到了现在,PAAS容器云时代已经慢慢步入舞台了。之前大家进入云计算领域,一般是从KVM、OpenStack入手。那么容器云时代,你可以从Docker、Kubernetes入手。其实本人写到这,有个很强烈的感受,那就是技术更新实在是太快了,本人之前花了两三年的时间掌握了KVM、OpenStack。本想吃点老本轻松一下,可是发现,根本就不能有这想法,因为容器的到来必将对OpenStack这样的平台有一定的冲击。IT一直都是朝着轻量、高性能、高可用的模式向前发展。所以,我们只能不断学习。不然,就会落下!

    Docker系列学习文章 – 什么是容器技术?(一)

    一、什么是容器?

    容器这个词,当你第一眼看它或许脑子里是这东西:瓶瓶罐罐、装水、装其他东西的玩意。

    不管是什么,总的来说,容器给人第一印象就是——“装”。

    那今天我们要说的容器技术是怎么一个概念呢?其实,IT里的容器技术是英文单词Linux Container的直译。container这个单词有集装箱、容器的含义(主要偏集装箱意思)。不过,在中文环境下,咱们要交流要传授,如果翻译成“集装箱技术” 就有点拗口,所以结合中国人的吐字习惯和文化背景,更喜欢用容器这个词。不过,如果要形象的理解Linux Container技术的话,还是得念成集装箱会比较好。我们知道,海边码头里的集装箱是运载货物用的,它是一种按规格标准化的钢制箱子。集装箱的特色,在于其格式划一,并可以层层重叠,所以可以大量放置在特别设计的远洋轮船中(早期航运是没有集装箱概念的,那时候货物杂乱无章的放,很影响出货和运输效率)。有了集装箱,那么这就更加快捷方便的为生产商提供廉价的运输服务。

    因此,IT世界里借鉴了这一理念。早期,大家都认为硬件抽象层基于hypervisor的虚拟化方式可以最大程度上提供虚拟化管理的灵活性。各种不同操作系统的虚拟机都能通过hypervisor(KVM、XEN等)来衍生、运行、销毁。然而,随着时间推移,用户发现hypervisor这种方式麻烦越来越多。为什么?因为对于hypervisor环境来说,每个虚拟机都需要运行一个完整的操作系统以及其中安装好的大量应用程序。但实际生产开发环境里,我们更关注的是自己部署的应用程序,如果每次部署发布我都得搞一个完整操作系统和附带的依赖环境,那么这让任务和性能变得很重和很低下。

    基于上述情况,人们就在想,有没有其他什么方式能让人更加的关注应用程序本身,底层多余的操作系统和环境我可以共享和复用?换句话来说,那就是我部署一个服务运行好后,我再想移植到另外一个地方,我可以不用再安装一套操作系统和依赖环境。这就像集装箱运载一样,我把货物一辆兰博基尼跑车(好比开发好的应用APP),打包放到一容器集装箱里,它通过货轮可以轻而易举的从上海码头(CentOS7.2环境)运送到纽约码头(Ubuntu14.04环境)。而且运输期间,我的兰博基尼(APP)没有受到任何的损坏(文件没有丢失),在另外一个码头卸货后,依然可以完美风骚的赛跑(启动正常)。

    Linux Container容器技术的诞生(2008年)就解决了IT世界里“集装箱运输”的问题。Linux Container(简称LXC)它是一种内核轻量级的操作系统层虚拟化技术。Linux Container主要由Namespace和Cgroup两大机制来保证实现。那么Namespace和Cgroup是什么呢?刚才我们上面提到了集装箱,集装箱的作用当然是可以对货物进行打包隔离了,不让A公司的货跟B公司的货混在一起,不然卸货就分不清楚了。那么Namespace也是一样的作用,做隔离。光有隔离还没用,我们还需要对货物进行资源的管理。同样的,航运码头也有这样的管理机制:货物用什么样规格大小的集装箱,货物用多少个集装箱,货物哪些优先运走,遇到极端天气怎么暂停运输服务怎么改航道等等... 通用的,与此对应的Cgroup就负责资源管理控制作用,比如进程组使用CPU/MEM的限制,进程组的优先级控制,进程组的挂起和恢复等等。

    二、容器技术的特点

    容器的特点其实我们拿跟它跟硬件抽象层虚拟化hypervisor技术对比就清楚了,我们之前也提到过,传统的虚拟化(虚拟机)技术,创建环境和部署应用都很麻烦,而且应用的移植性也很繁琐,比如你要把vmware里的虚拟机迁移到KVM里就很繁琐(需要做镜像格式的转换)。那么有了容器技术就简单了,总结下容器技术主要有三个特点:

    1. 极其轻量:只打包了必要的Bin/Lib;
    2. 秒级部署:根据镜像的不同,容器的部署大概在毫秒与秒之间(比虚拟机强很多);
    3. 易于移植:一次构建,随处部署;
    4. 弹性伸缩:Kubernetes、Swam、Mesos这类开源、方便、好使的容器管理平台有着非常强大的弹性管理能力。

    三、容器的标准化

    当前,docker几乎是容器的代名词,很多人以为docker就是容器。其实,这是错误的认识,除了docker 还有coreos。所以,容器世界里并不是只有docker一家。既然不是一家就很容易出现分歧。任何技术出现都需要一个标准来规范它,不然各搞各的很容易导致技术实现的碎片化,出现大量的冲突和冗余。因此,在2015年,由Google,Docker、CoreOS、IBM、微软、红帽等厂商联合发起的OCI(Open Container Initiative)组织成立了,并于2016年4月推出了第一个开放容器标准。标准主要包括runtime运行时标准和image镜像标准。标准的推出,有助于替成长中市场带来稳定性,让企业能放心采用容器技术,用户在打包、部署应用程序后,可以自由选择不同的容器Runtime;同时,镜像打包、建立、认证、部署、命名也都能按照统一的规范来做。

    两种标准主要包含以下内容:

    1. 容器运行时标准 (runtime spec)

    a). creating:使用 create 命令创建容器,这个过程称为创建中
    b). created:容器创建出来,但是还没有运行,表示镜像和配置没有错误,容器能够运行在当前平台
    c). running:容器的运行状态,里面的进程处于 up 状态,正在执行用户设定的任务
    d). stopped:容器运行完成,或者运行出错,或者 stop 命令之后,容器处于暂停状态。这个状态,容器还有很多信息保存在平台中,并没有完全被删除

    1. 容器镜像标准(image spec)

    a). 文件系统:以 layer 保存的文件系统,每个 layer 保存了和上层之间变化的部分,layer 应该保存哪些文件,怎么表示增加、修改和删除的文件等;
    b). config 文件:保存了文件系统的层级信息(每个层级的 hash 值,以及历史信息),以及容器运行时需要的一些信息(比如环境变量、工作目录、命令参数、mount 列表),指定了镜像在某个特定平台和系统的配置。比较接近我们使用 docker inspect 看到的内容;
    c). manifest 文件:镜像的 config 文件索引,有哪些 layer,额外的 annotation 信息,manifest 文件中保存了很多和当前平台有关的信息;
    d). index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的 manifest 文件,使用 index 作为索引。

    四、容器的主要应用场景

    容器技术的诞生其实主要解决了PAAS的层的技术实现。像OpenStack、Cloudstack这样的技术是解决IAAS层的问题。IAAS层和PAAS层大家估计也听得很多了,关于他们的区别和特性我这里不在描述。那么容器技术主要应用在哪些场景呢?目前主流的有以下几种:

    1. 容器化传统应用
      容器不仅能提高现有应用的安全性和可移植性,还能节约成本。

    每个企业的环境中都有一套较旧的应用来服务于客户或自动执行业务流程。即使是大规模的单体应用,通过容器隔离的增强安全性、以及可移植性特点,也能从 Docker 中获益,从而降低成本。一旦容器化之后,这些应用可以扩展额外的服务或者转变到微服务架构之上。

    1. 持续集成和持续部署 (CI/CD)
      通过 Docker 加速应用管道自动化和应用部署,交付速度提高至少 13 倍。

    现代化开发流程快速、持续且具备自动执行能力,最终目标是开发出更加可靠的软件。通过持续集成 (CI) 和持续部署 (CD),每次开发人员签入代码并顺利测试之后,IT 团队都能够集成新代码。作为开发运维方法的基础,CI/CD 创造了一种实时反馈回路机制,持续地传输小型迭代更改,从而加速更改,提高质量。CI 环境通常是完全自动化的,通过 git 推送命令触发测试,测试成功时自动构建新镜像,然后推送到 Docker 镜像库。通过后续的自动化和脚本,可以将新镜像的容器部署到预演环境,从而进行进一步测试。

    1. 微服务
      加速应用架构现代化进程。

    应用架构正在从采用瀑布模型开发法的单体代码库转变为独立开发和部署的松耦合服务。成千上万个这样的服务相互连接就形成了应用。Docker 允许开发人员选择最适合于每种服务的工具或技术栈,隔离服务以消除任何潜在的冲突,从而避免“地狱式的矩阵依赖”。这些容器可以独立于应用的其他服务组件,轻松地共享、部署、更新和瞬间扩展。Docker 的端到端安全功能让团队能够构建和运行最低权限的微服务模型,服务所需的资源(其他应用、涉密信息、计算资源等)会适时被创建并被访问。

    1. IT 基础设施优化
      充分利用基础设施,节省资金。

    Docker 和容器有助于优化 IT 基础设施的利用率和成本。优化不仅仅是指削减成本,还能确保在适当的时间有效地使用适当的资源。容器是一种轻量级的打包和隔离应用工作负载的方法,所以 Docker 允许在同一物理或虚拟服务器上毫不冲突地运行多项工作负载。企业可以整合数据中心,将并购而来的IT资源进行整合,从而获得向云端的可迁移性,同时减少操作系统和服务器的维护工作。

    探索Docker 容器

    探索Docker 容器

    Docker 容器(Container)命令可以帮助你创建、启动、停止、查看和删除容器。让我们从一些常见的容器命令开始。

    启动一个容器

    要基于某个镜像启动一个容器,可以使用 docker run 命令。没有nginx镜像就拉取一个。例如:

    docker run -d -p 8089:80 nginx
    

    输出:

    root@debian:/home/x# docker run -d -p 8089:80 nginx
    f224e28c9211ac23bd5269423d7e1db56812586288d44b32d80e5ab5dbd8f42a
    

    这个命令会从 nginx 镜像启动一个新的容器,并将主机的 8089 端口映射到容器的 80 端口。-d 参数表示容器在后台运行。启动后,你可以通过访问 http://localhost:8089 来查看 nginx 容器的服务。

    查看正在运行的容器

    要查看当前所有正在运行的容器,可以使用以下命令:

    docker ps
    

    输出:

    root@debian:/home/x# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
    f224e28c9211   nginx     "/docker-entrypoint.…"   40 seconds ago   Up 39 seconds   0.0.0.0:8089->80/tcp, :::8089->80/tcp   hopeful_cori
    

    这个命令会列出所有正在运行的容器,包括容器 ID、使用的镜像、创建时间、状态、暴露的端口以及容器名称等信息。如果你想查看所有的容器(包括停止的),可以加上 -a 参数:

    docker ps -a
    

    停止一个运行中的容器

    如果你想停止某个正在运行的容器,可以使用 docker stop 命令,后面跟上容器的 ID 或名称。例如:

    docker stop 容器ID或名称
    

    上面运行的容器ID是f224e28c9211,这里就关闭这个ID的容器。

    docker stop f224e28c9211
    

    输出:

    root@debian:~/home/x~# docker stop f224e28c9211
    f224e28c9211
    

    再次输入docker ps -a检查一下,可以看到刚刚的容器f224e28c9211已经停止,STATUS状态是Exit(0)

    root@debian:~# docker ps -a
    CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                          PORTS     NAMES
    f224e28c9211   nginx         "/docker-entrypoint.…"   3 minutes ago    Exited (0) About a minute ago             hopeful_cori
    94a60b0d3c48   hello-world   "/hello"                 51 minutes ago   Exited (0) 50 minutes ago                 competent_haslett
    

    启动一个已停止的容器

    要重新启动一个已停止的容器,可以使用 docker start 命令。例如:
    docker start 容器ID或名称

    这个命令会将指定的容器从停止状态重新启动,而不需要重新创建容器。如启动刚刚停止的容器。

    docker start f224e28c9211
    

    输出:

    root@debian:~# docker start f224e28c9211
    f224e28c9211
    

    再次输入docker ps -a检查一下,可以看到刚刚的容器f224e28c9211已经启动,STATUS状态是Up 56 Seconds.(这个56是启动后运行了56秒)

    root@debian:~# docker ps -a
    CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                      PORTS                                   NAMES
    f224e28c9211   nginx         "/docker-entrypoint.…"   6 minutes ago    Up 56 seconds               0.0.0.0:8089->80/tcp, :::8089->80/tcp   hopeful_cori
    94a60b0d3c48   hello-world   "/hello"                 54 minutes ago   Exited (0) 54 minutes ago
    

    进入一个正在运行的容器

    有时,你可能需要进入一个正在运行的容器,检查其内部情况或执行一些命令。可以使用 docker exec 命令。例如:

    docker exec -it 容器ID或名称 /bin/bash
    

    进入刚刚运行的容器

    docker exec -it f224e28c9211 /bin/bash
    

    输出:

    root@debian:~# docker exec -it f224e28c9211 /bin/bash
    root@f224e28c9211:/# ls
    bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    root@f224e28c9211:/#
    

    这个命令会启动一个交互式的 shell(通常是 bash),让你直接进入容器的命令行环境。
    除此之外,我们还可以在run的时候加-it进入容器,就像这样

    root@debian:~# docker run  -it nginx /bin/bash
    root@a7735690088f:/#
    

    删除一个容器

    如果你不再需要某个容器,可以使用 docker rm 命令将其删除。例如:

    docker rm 容器ID或名称
    

    在删除之前,确保容器已经停止。如果容器还在运行,可以先使用 docker stop 停止它,或者直接使用 -f 参数强制删除:

    docker rm -f 容器ID或名称
    

    删除刚刚运行的容器

    docker rm -f f224e28c9211
    

    输出:

    root@debian:~# docker rm -f f224e28c9211
    f224e28c9211
    

    探索Docker 镜像

    探索Docker 镜像

    查看docker镜像列表

    docker images
    

    输出:

    root@debian:~# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    hello-world   latest    d2c94e258dcb   18 months ago   13.3kB
    

    因为刚刚运行了docker run hello-world,所以这里只有一个镜像hello-world
      REPOSITORY:仓库,也是镜像名称。
      TAG:标签,也是版本号,镜像会有不同的版本号。
      IMAGE ID:镜像id,根据这个id我们可以区分不同的镜像,也可以对某个镜像进行操作。
      CREATED:创建时间。
      SIZE:镜像的大小

    拉取Docker镜像

    如果你想从Docker仓库(比如 Docker Hub)获取一个新的镜像,可以使用 docker pull 命令。
    例如,如果你想拉取一个官方的 nginx 镜像,可以执行以下命令:

    docker pull nginx
    

    输出:

    root@debian:~# docker pull nginx
    Using default tag: latest
    latest: Pulling from library/nginx
    a480a496ba95: Pull complete
    f3ace1b8ce45: Pull complete
    11d6fdd0e8a7: Pull complete
    f1091da6fd5c: Pull complete
    40eea07b53d8: Pull complete
    6476794e50f4: Pull complete
    70850b3ec6b2: Pull complete
    Digest: sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb
    Status: Downloaded newer image for nginx:latest
    docker.io/library/nginx:latest
    

    这个命令会从 Docker Hub 下载最新版本的 nginx 镜像到你的本地。
    下载完成后,你可以使用 docker images 再次查看,确认这个镜像已经存在。

    root@debian:~# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    nginx         latest    3b25b682ea82   3 weeks ago     192MB
    hello-world   latest    d2c94e258dcb   18 months ago   13.3kB
    

    指定版本拉取 Docker 镜像

    DOkcer默认拉取最新版本镜像。有时候,你可能不想拉取镜像的最新版本,而是想要某个特定的版本。
    这时,你可以通过 docker pull 命令加上镜像名和标签(tag)来拉取指定版本的镜像。格式如下:

    docker pull 镜像名:tag
    

    例如,如果你想拉取 nginx 的 1.19 版本,可以执行以下命令:

    docker pull nginx:1.19
    

    输出:

    root@debian:~# docker pull nginx:1.19
    1.19: Pulling from library/nginx
    69692152171a: Pull complete
    49f7d34d62c1: Pull complete
    5f97dc5d71ab: Pull complete
    cfcd0711b93a: Pull complete
    be6172d7651b: Pull complete
    de9813870342: Pull complete
    Digest: sha256:df13abe416e37eb3db4722840dd479b00ba193ac6606e7902331dcea50f4f1f2
    Status: Downloaded newer image for nginx:1.19
    docker.io/library/nginx:1.19
    

    这里的 :1.19 就是镜像的标签,表示你要拉取的特定版本。标签通常用来标识不同的版本或变体,比如某个软件的最新稳定版、测试版或历史版本。通过指定标签,你可以确保拉取的镜像是你所需要的那个版本。如果你省略了标签部分,Docker 会默认拉取这个镜像的最新版本(latest 标签)。

    使用 docker images查看

    root@debian:~# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    nginx         latest    3b25b682ea82   3 weeks ago     192MB
    hello-world   latest    d2c94e258dcb   18 months ago   13.3kB
    nginx         1.19      f0b8a9a54136   3 years ago     133MB
    

    删除 Docker 镜像

    当你不再需要某个镜像时,可以通过 docker rmi 命令将其删除,释放空间。例如,如果你想删除我们刚刚拉取的 nginx 镜像,可以这样做:

    docker rmi nginx
    

    输出:

    root@debian:~# docker rmi nginx
    Untagged: nginx:latest
    Untagged: nginx@sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb
    Deleted: sha256:3b25b682ea82b2db3cc4fd48db818be788ee3f902ac7378090cf2624ec2442df
    Deleted: sha256:3e8a4396bcdb62aeb916ec1e4cf64500038080839f049c498c256742dd842334
    Deleted: sha256:8dd6a711fbdd252eba01f96630aa132c4b4e96961f09010fbbdb11869865f994
    Deleted: sha256:9368c52198f80c9fb87fc3eaf7770afb7abb3bfd4120a8defd8a8f1a68ff375d
    Deleted: sha256:46834c975bf2d807053675d76098806736ee94604c650aac5fe8b5172ab008c8
    Deleted: sha256:6e433330e8b1553bee0637fac3b1e66c994bb2c0cab7b2372d2584171d1c93d8
    Deleted: sha256:fbc611fa4a4aff4cf0bfd963c49e2c416ff8047c9f84c2dc9328d3b833f1118d
    Deleted: sha256:98b5f35ea9d3eca6ed1881b5fe5d1e02024e1450822879e4c13bb48c9386d0ad
    

    注意,如果某个镜像正被某个容器使用,你会需要先停止并删除相关的容器才能删除这个镜像。

    强制删除 Docker 镜像

    有时你可能需要删除某个镜像,但该镜像可能正被其他容器使用,或者因为某些依赖关系导致无法正常删除。此时,你可以使用 docker image rm 命令加上 -f 参数来强制删除镜像。格式如下:

    docker image rm -f 镜像名称/镜像ID
    

    例如,如果你想强制删除一个名为 nginx 的镜像,可以执行以下命令。
    刚刚删掉了nginx,先拉回来再删除。

    docker pull nginx
    docker image rm -f nginx
    

    输出:

    root@debian:/home/x# docker image rm -f nginx
    Untagged: nginx:latest
    Untagged: nginx@sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb
    Deleted: sha256:3b25b682ea82b2db3cc4fd48db818be788ee3f902ac7378090cf2624ec2442df
    Deleted: sha256:3e8a4396bcdb62aeb916ec1e4cf64500038080839f049c498c256742dd842334
    Deleted: sha256:8dd6a711fbdd252eba01f96630aa132c4b4e96961f09010fbbdb11869865f994
    Deleted: sha256:9368c52198f80c9fb87fc3eaf7770afb7abb3bfd4120a8defd8a8f1a68ff375d
    Deleted: sha256:46834c975bf2d807053675d76098806736ee94604c650aac5fe8b5172ab008c8
    Deleted: sha256:6e433330e8b1553bee0637fac3b1e66c994bb2c0cab7b2372d2584171d1c93d8
    Deleted: sha256:fbc611fa4a4aff4cf0bfd963c49e2c416ff8047c9f84c2dc9328d3b833f1118d
    Deleted: sha256:98b5f35ea9d3eca6ed1881b5fe5d1e02024e1450822879e4c13bb48c9386d0ad
    [plain]</p>
    <p>或者,如果你想根据镜像的 ID 来删除(镜像 ID 通常是镜像名称的简写),可以这样做:
    [plain]
    docker image rm -f 123456789abc
    

    这里的 -f 参数表示“force”,即强制删除,无论该镜像是否正在被使用或是否有依赖容器。请注意,使用 -f 强制删除镜像时要谨慎,因为这可能会影响正在运行的容器,或破坏相关联的其他镜像或依赖项。

    搜索Docker官方镜像

    如果你想查找某个镜像,可以使用 docker search 命令。例如,如果你想找 nginx 的官方镜像,可以执行以下命令:

    docker search nginx
    

    这个命令会在 Docker Hub 上搜索包含 “nginx” 关键字的所有镜像,并显示一系列相关的镜像列表。你会看到每个镜像的名称、描述、星级评分(由社区用户给出)、是否为官方镜像以及其他信息。
    在搜索结果中,你可以看到一行 nginx,带有 “OFFICIAL” 标记,这表明它是由 Docker 官方维护的镜像,通常可以放心使用。

    这些是基本的docker的镜像的命令。

    Debian12 安装Docker

    Debian12 安装Docker

    安装Docker

    先更新系统

    apt update
    

    安装Docker

    apt -y install docker.io
    

    测试是否安装成功,以下三个命令随便一个都可以。

    docker -v
    docker --version
    docker version
    

    输出:

    Docker version 20.10.24+dfsg1, build 297e128
    

    更改DOCKER HUB源
    修改/etc/docker/daemon.json文件,没有的话nano会自动创建一个

    nano /etc/docker/daemon.json
    

    输入以下内容:

    {
      "registry-mirrors": [
            "https://registry.hub.docker.com",
            "http://hub-mirror.c.163.com",
            "https://mirror.baidubce.com",
            "https://docker.mirrors.sjtug.sjtu.edu.cn",
            "https://docker.nju.edu.cn"
      ]
    }

    CTRL+O,回车键保存,CTRL+X推出nano

    加载daemon.json文件更新配置,重启Docker

    systemctl daemon-reload
    systemctl restart docker
    

    查看镜像源地址修改情况,检查最后几行Registry Mirrors是不是刚刚修改的地址

    docker info
    

    运行一个镜像测试一下

    docker run hello-world
    

    docker run hello-world 是一个 Docker 命令,用于运行一个名为 hello-world 的 Docker 容器。这个命令首先会在本地查找 hello-world 镜像,如果没有找到,Docker 会自动从 Docker Hub 上下载这个镜像,然后运行这个镜像。
    如果你运行了 docker run hello-world 命令,你应该会看到一些欢迎信息,通常是一条打印出 "Hello from Docker!" 的消息。

    输出如下。

    root@debian:/etc/docker# docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    c1ec31eb5944: Pull complete
    Digest: sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (amd64)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash
    
    Share images, automate workflows, and more with a free Docker ID:
     https://hub.docker.com/
    
    For more examples and ideas, visit:
     https://docs.docker.com/get-started/

    OK,Docker安装成功了。

    安装docker-compose

    虽然现在用不到,以后会用到。

    apt install docker-compose -y
    

    测试docker-compose是否安装成功,以下三个命令随便一个都可以。

    docker-compose -v
    docker-compose --version
    docker-compose version
    

    输出以下差不多的内容表示安装成功。

    docker-compose version 1.29.2, build unknown
    

    Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。