【容器应用系列教程】容器介绍、Docker的安装和基本操作

一、关于容器container

container01

创建保证某业务可正常运行的必备的应用程序/指令

1.常用的容器管理工具

  • docker
    • 基于golang语言开发
    • 开源的
    • c/s架构 client/server架构
    • docker-ce社区版、docker-ee企业版
  • podman
    • 红帽公司开发

2.容器的优势

  • 创建速度快、秒级
  • 便于业务的部署、迁移
  • 容器间共享物理机的内核
  • 缺点:安全性低

3.容器的核心技术

  • namespace命名空间
    • 实现容器间的资源(用户、进程)隔离
  • cgroup
    • 实现容器的资源(CPU、内存)限制
  • 容器的三要素:容器镜像仓库

二、Centos7安装Docker-ce

1.配置yum源和docker国内源

[root@lvm ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

如果没有vim请安装yum install -y vim

[root@lvm ~]# vim /etc/yum.repos.d/docker.repo
[docker-ce]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
enabled=1
gpgcheck=0

建立yum缓存

[root@lvm ~]# yum clean all && yum makecache

2.安装Docker-ce

[root@lvm ~]# yum install -y docker-ce docker-ce-cli containerd.io

3.启动Docker-ce

[root@lvm ~]# systemctl enable --now docker

4.配置Docker-ce国内镜像加速

由于国内已经无法访问https://hub.docker.com,请一定要做这一步!

[root@lvm ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"]
}

重启Docker,让配置文件生效

[root@lvm ~]# systemctl restart docker

查看Docker版本

[root@lvm ~]# docker version
Client: Docker Engine - Community
 Version:           24.0.2
 API version:       1.43
 Go version:        go1.20.4
 Git commit:        cb74dfc
 Built:             Thu May 25 21:55:21 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.2
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.4
  Git commit:       659604f
  Built:            Thu May 25 21:54:24 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.21
  GitCommit:        3dce8eb055cbb6872793272b4f20ed16117344f8
 runc:
  Version:          1.1.7
  GitCommit:        v1.1.7-0-g860f061
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

三、Docker命令基本的操作

1.查找镜像

# docker search 镜像名
[root@lvm ~]# docker search nginx
NAME                                              DESCRIPTION                                      STARS     OFFICIAL   AUTOMATED
nginx                                             Official build of Nginx.                         18582     [OK]       
unit                                              Official build of NGINX Unit: Universal Web …   5         [OK]

2.拉取镜像

# docker pull 镜像名
[root@lvm ~]# docker pull nginx:latest

Nginx软件名:标签
latest代表最新版,如果不写标签,默认同样拉取的是最新版的镜像

3.查看本地镜像

# docker images
或
# docker image ls
[root@lvm ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    f9c14fe76d50   8 days ago      143MB
busybox      latest    8135583d97fe   13 days ago     4.86MB
centos       7         eeb6ee3f44bd   20 months ago   204MB

[root@lvm ~]# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    f9c14fe76d50   8 days ago      143MB
busybox      latest    8135583d97fe   13 days ago     4.86MB
centos       7         eeb6ee3f44bd   20 months ago   204MB

4.创建容器

# docker run <选项> [镜像名] 命令
[root@localhost ~]# docker run -tid centos:7 sleep 10
[root@localhost ~]# docker run -tid centos:7 /bin/bash
[root@localhost ~]# docker run -tid centos:7
[root@localhost ~]# docker run -tid centos:7 ls
  • -it在容器内部模拟一个终端
  • -d容器保持后台运行
  • 重要核心:
    • 容器的运行是依赖于持续的进程
    • 一个容器只运行一个任务
    • 创建容器后面的命令,决定容器是否可持续运行。

5.查看容器

查看正在运行的容器

[root@lvm ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

查看所有容器

[root@lvm ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED       STATUS                           PORTS     NAMES
528a4264f3ae   centos:7   "/bin/bash"   3 hours ago   Exited (137) About an hour ago             centos

6.删除容器

在删除容器前,先停止容器,或者添加-f强制删除

关于容器ID,可以使用docker ps -a查看容器ID

# docker stop 容器名/容器ID
# docker rm 容器名/容器ID
# docker rm -f 容器名/容器ID

7.删除镜像

可以使用docker images查看镜像

# docker rmi 镜像名/镜像ID

8.连接容器

# docker exec -it 容器名/容器ID 要执行的命令
[root@lvm ~]# docker exec -it centos /bin/bash
[root@lvm /]# ls

9.查看容器的详细信息

# docker inspect 容器名/容器ID

10.查看容器日志

# docker logs 容器名/容器ID

11.拷贝物理机文件到容器内

# docker ps 文件 容器名/容器ID:容器内路径
[root@lvm ~]# docker cp /root/file01 centos:/tmp/
Successfully copied 1.54kB to centos:/tmp/

12.拷贝容器内文件到物理机

# docker cp 容器名/容器ID:要拷贝的文件 物理机路径
[root@lvm ~]# docker cp centos:/123.mp3 /root/
Successfully copied 1.54kB to /root/

13.导出容器

# docker export -o 文件路径 容器名/容器ID
[root@lvm ~]# docker export -o /root/centos.tar centos

14.导入容器

# docker import 文件 

四、创建容器时的选项参数

# docker run <选项> [镜像名] 命令

1.模拟终端

  • -it
[root@localhost ~]# docker run -it centos:7

2.保持后台运行

  • -d
[root@localhost ~]# docker run -itd centos:7

3.指定容器名字

  • --name名字
[root@localhost ~]# docker run -itd --name centos01 centos:7

4.指定容器主机名

  • --hostname=主机名
[root@localhost ~]# docker run -itd --name centos02  --hostname=web_server centos:7

5.映射容器内部端口(发布服务)

  • -p物理机端口:容器内部端口
  • -P(大写P)随机映射端口
[root@lvm ~]# docker run -itd --name nginx01 -p 8888:80 nginx
[root@lvm ~]# docker run -itd --name nginx02 -P nginx

可以看到小写p指定端口是8888,而大写P是个随机端口32768

[root@lvm ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                   CREATED          STATUS          PORTS                                     NAMES
89d81e09cb12   nginx      "/docker-entrypoint.…"   5 seconds ago    Up 5 seconds    0.0.0.0:32768->80/tcp, :::32768->80/tcp   nginx02
297bc0b75f48   nginx      "/docker-entrypoint.…"   24 seconds ago   Up 23 seconds   0.0.0.0:8888->80/tcp, :::8888->80/tcp     nginx01

6.设置容器重启策略

一般用于容器开机自启动

  • --restart=always/unless-stopped
    • always在容器退出时总是重启容器
    • unless-stopped在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
[root@lvm ~]# docker run -it -d -p 8090:80 --name nginx03 --restart=always nginx

7.对容器做资源限制

  • 针对CPU、内存进行限制
  • 默认创建容器时,物理机是不会对容器做资源限制的,如果容器数量过多,导致oom现象,物理机启动oom-killler机制随机杀进程,可能会容器不能正常工作

A.对容器CPU限制

  • --cpus=限制数量
[root@lvm ~]# docker run -tid --cpus=2 centos /bin/bash

B.对容器内存限制

  • --memory=限制大小
[root@lvm ~]# docker run -tid --memory=1024M centos /bin/bash

8.向容器内部传递参数(重要)

  • -e 变量名=要传递的参数
[root@lvm ~]# docker run -itd -e USER=wangshengjj --name centos01 centos:7

查看容器内的变量

[root@lvm ~]# docker exec -it centos01 bash
[root@b67cb71fc38f /]# echo $USER
wangshengjj

9.实现容器数据持久化保存(重要)

  • -v 物理机目录:容器内目录
[root@lvm ~]# mkdir -p /mysql/data
[root@lvm ~]# docker run -itd --name mysql01 -p 3306:3306 -v /mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="WWW.1.com" mysql:5.7

容器内部/var/lib/mysql目录下的内容,已经被映射到了物理机的/mysql/data

[root@lvm ~]# ls /mysql/data/
auto.cnf         client-key.pem  ib_logfile1  performance_schema  server-key.pem
ca-key.pem       ib_buffer_pool  ibtmp1       private_key.pem     sys
ca.pem           ibdata1         mysql        public_key.pem
client-cert.pem  ib_logfile0     mysql.sock   server-cert.pem

10.设置容器之间的网络别名

如果我们无法直接控制容器之间的网络(因为容器都是DHCP网络),所以当有容器要经常互相通信的时候,就可以在创建的时候设置网络别名

  • --link=要连接的容器名:自己起个别名
[root@lvm ~]# docker run -itd --name demo centos:7
82b7d2b1d0255142eefc69f87682fed04074b38be2ccd03c9da3abfd84456af8

[root@lvm ~]# docker run -itd --link=demo:web_server centos:7
4b4fbcc4aae145c3f064212e44bda9c9e986d2d8e8147c9fa51a64ad5600dac9

进入第二个容器测试

[root@lvm ~]# docker exec -it 4b4fbcc /bin/bash

[root@4b4fbcc4aae1 /]# ping web_server
PING web_server (172.17.0.3) 56(84) bytes of data.
64 bytes from web_server (172.17.0.3): icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from web_server (172.17.0.3): icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from web_server (172.17.0.3): icmp_seq=3 ttl=64 time=0.208 ms

本质上Docker自动帮我们加入了主机名解析

[root@4b4fbcc4aae1 /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	web_server 82b7d2b1d025 demo
172.17.0.5	4b4fbcc4aae1

五、示例

1.利用Docker部署一个Wordpress

准备数据目录

[root@lvm ~]# mkdir -p /mysql/{master_data,slave_data}

准备主从复制配置文件

[root@lvm ~]# vim /mysql/master_my.cnf
[mysqld]
server_id=10
log_bin=master
gtid_mode=on
enforce_gtid_consistency=true
[root@lvm ~]# vim /mysql/slave_my.cnf
[mysqld]
server_id=11
log_bin=slave
gtid_mode=on
enforce_gtid_consistency=true

先部署2个数据库

root@lvm ~]# docker run -itd -e MYSQL_ROOT_PASSWORD="WWW.1.com" -v /mysql/master_data:/var/lib/mysql -v /mysql/master_my.cnf:/etc/my.cnf --restart=always --name=masterDB mysql:5.7
[root@lvm ~]# docker run -itd --link=masterDB:masterdb --name=slaveDB -e MYSQL_ROOT_PASSWORD="WWW.1.com" -v /mysql/slave_data:/var/lib/mysql -v /mysql/slave_my.cnf:/etc/my.cnf --restart=always mysql:5.7
  • --link用于配置主从复制连接
配置主从复制

关于MySQL主从复制教程:https://www.wsjj.top/archives/76

[root@lvm ~]# docker exec -it masterDB /bin/bash
bash-4.2# mysql -uroot -p
mysql> grant replication slave on *.* to 'repluser'@'%' identified by 'WWW.1.com';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create database wordpress;
Query OK, 1 row affected (0.00 sec)

mysql> grant all on wordpress.* to 'wordpress'@'%' identified by 'WWW.1.com';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> exit
Bye
bash-4.2# exit
exit
[root@lvm ~]# 
[root@lvm ~]# docker exec -it slaveDB /bin/bash
bash-4.2# mysql -uroot -p
mysql> change master to
    -> master_host="masterdb",
    -> master_user="repluser",
    -> master_password="WWW.1.com",
    -> master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: masterdb
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master.000003
          Read_Master_Log_Pos: 960
               Relay_Log_File: e286493f40f4-relay-bin.000003
                Relay_Log_Pos: 1167
        Relay_Master_Log_File: master.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

创建WordPress容器

[root@lvm ~]# docker run -itd --name wordpress --link=masterDB:masterdb -p 80:80 --restart=always -e WORDPRESS_DB_HOST="masterdb" -e WORDPRESS_DB_USER="wordpress" -e WORDPRESS_DB_PASSWORD="WWW.1.com" -e WORDPRESS_DB_NAME="wordpress" -e WORDPRESS_TABLE_PREFIX="wp_" wordpress
浏览器测试

container02

container03

Wordpress安装redis插件

启用redis容器
[root@lvm ~]# docker run -itd --name redis --restart=always -p 6379:6379 redis:latest
Wordpress网页端安装redis插件

下载完,先不要启动插件

container06

修改Wordpress配置文件
[root@lvm ~]# docker cp wordpress:/var/www/html/wp-content/plugins/redis-cache/includes/object-cache.php /root/
[root@lvm ~]# vim /root/object-cache.php
protected function build_parameters() {
        $parameters = [
            'scheme' => 'tcp',
            'host' => '192.168.140.16',	#指定redis库连接地址
            'port' => 6379,
            'database' => 0,
            'timeout' => 1,
            'read_timeout' => 1,
            'retry_interval' => null,
            'persistent' => false,
        ];
[root@lvm ~]# docker cp object-cache.php wordpress:/var/www/html/wp-content/plugins/redis-cache/includes/
[root@lvm ~]# docker cp wordpress:/var/www/html/wp-config.php /root/
[root@lvm ~]# vim /root/wp-config.php
#在配置文件末尾添加以下几行内容
define('WP_REDIS_HOST', '192.168.140.16');	#物理机IP
define('WP_REDIS_PORT', '6379');
define('WP_REDIS_DATABASE', '0');
#define('WP_REDIS_PASSWORD', '123456');	#redis连接密码
docker cp /root/wp-config.php wordpress:/var/www/html/wp-config.php
回到wordpress后台,启动redis插件

container07

2.利用Docker搭建一个haproy负载均衡和2tomcat站点

先部署2tomcat站点,然后再配置haproxy做负载均衡

创建网页目录和准备java项目

[root@lvm ~]# mkdir -p /tomcat/webapps
[root@lvm ~]# ls /tomcat/webapps
phone_war.war

创建2个tomcat容器

[root@lvm ~]# docker run -itd --name tomcat01 --restart=always -v /tomcat/webapps:/usr/local/tomcat/webapps -p 8080:8080 tomcat:8
[root@lvm ~]# docker run -itd --name tomcat02 --restart=always -v /tomcat/webapps:/usr/local/tomcat/webapps -p 8080:8080 tomcat:8

准备HAproxy的配置文件

[root@lvm ~]# mkdir -p /haproxy
[root@lvm ~]# vim /haproxy/haproxy.cfg
global
  stats socket /var/lib/haproxy/stats user haproxy group haproxy mode 660 level admin expose-fd listeners
  log stdout format raw local0 info

defaults
  mode http
  timeout client 10s
  timeout connect 5s
  timeout server 10s
  timeout http-request 10s
  log global

frontend stats
  bind *:8888
  stats enable
  stats uri /
  stats refresh 10s

frontend myfrontend
  bind :81
  default_backend webservers

backend webservers
  server s1 tomcat01:8080 check
  server s2 tomcat02:8080 check

启动HAproxy容器

docker run -itd --name haproxy --restart=always --user=root -p 81:81 -p 8888:8888 --link=tomcat01:tomcat01 --link=tomcat02:tomcat02 -v /haproxy/:/usr/local/etc/haproxy:ro haproxy

浏览器访问测试

container04

container05