Docker之容器

1 容器简介

容器(Container):容器是一种轻量级、可移植、并将应用程序进行的打包的技术,使应用程序可以在几乎任何地方以相同的方式运行

•Docker将镜像文件运行起来后,产生的对象就是容器。容器相当于是镜像运行起来的一个实例。

•容器具备一定的生命周期。

•另外,可以借助docker ps命令查看运行的容器,如同在linux上利用ps命令查看运行着的进程那样。


2 容器与虚拟机

•容器和虚拟机一样,都会对物理硬件资源进行共享使用。

•容器和虚拟机的生命周期比较相似(创建、运行、暂停、关闭等等)。

•容器中或虚拟机中都可以安装各种应用,如redis、mysql、nginx等。也就是说,在容器中的操作,如同在一个虚拟机(操作系统)中操作一样。

•同虚拟机一样,容器创建后,会存储在宿主机上:linux上位于/var/lib/docker/containers下


注意:容器并不是虚拟机,但它们有很多相似的地方

•虚拟机的创建、启动和关闭都是基于一个完整的操作系统。一个虚拟机就是一个完整的操作系统。而容器直接运行在宿主机的内核上,其本质上以一系列进程的结合。

•容器是轻量级的,虚拟机是重量级的。首先容器不需要额外的资源来管理(不需要Hypervisor、Guest OS),虚拟机额外更多的性能消耗;其次创建、启动或关闭容器,如同创建、启动或者关闭进程那么轻松,而创建、启动、关闭一个操作系统就没那么方便了。

•也因此,意味着在给定的硬件上能运行更多数量的容器,甚至可以直接把Docker运行在虚拟机上。

3 容器生命周期

3.1 虚拟机的生命周期

3.2 容器的生命周期

4 容器生命周期管理

4.1 容器查看

# 查看机器上正在运行的所有容器
docker ps

# 查看宿主机上所有的容器(包括停止的)
docker ps -a

# 查看最后一次运行的容器
docker ps –l

# 查看停止的容器
docker ps -f status=exited

4.2 容器创建 – docker create

# 作用:
	利用镜像创建出一个Created 状态的待启动容器
    
# 命令格式:
	docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
    
# 命令参数(OPTIONS):查看更多
	-t, --tty           		分配一个伪TTY,也就是分配虚拟终端bash
    -i, --interactive    	    以交互模式运行容器,加入-t-i这两个参数,容器启动后会直接进入容器。分配一个伪终端
    --name          		    为容器起名,如果没有指定将会随机产生一个名称
    
# 命令参数(COMMAND\ARG):
	COMMAND 表示容器启动后,需要在容器中执行的命令,如ps、ls 等命令
	ARG 表示执行 COMMAND 时需要提供的一些参数,如ps 命令的 aux、ls命令的-a等等
    
# 命令演示:
# ps -A 提前预设一个命令,容器一启动就会执行
# 当容器启动-->执行ps -A,命令一执行完,容器就停止了,因为它不是可以夯住的命令
docker create --name test-container centos ps -A
docker create -ti --name test-container2 centos /bin/bash


# 我们拉的centous镜像是纯净版,里面没有sshd服务端,如果启了一个centos7的容器,宿主机不能直接用ssh连接容器(进到容器做交互)
# 要么装一个sshd服务端,要么下载第三方集成了sshd服务端的镜像。
# 这里用的-t,并不是真正的进到容器,只是分配一个伪终端,相当于启一个bash窗口,和宿主机做交互

下面以redis和centos镜像先创建容器,再启动,验证容器是否会夯住或直接停止

# 以centos镜像创建容器,然后启动
# 以下4个命令都只是创建出容器
docker create --name test-container1 centos:centos7 
docker create --name test-container2 centos:centos7 /bin/bash
docker create -ti --name test-container3 centos:centos7
docker create -ti --name test-container4 centos:centos7 /bin/bash

# docker start 启动容器
test-container1和test-container2,启动后容器停止了,因为没有可以夯住的命令
test-container3和test-container4,启动后容器夯住了,维持后台运行
# 总结:centos容器启动后默认运行 /bin/bash;创建时如果加了 -i或-t参数,运行bash的命令没有结束,容器就不会停止
# 注:/bin/bash的作用是表示载入容器后运行bash ,docker中必须要保持一个进程的运行,要不然整个容器启动后就会马上kill掉
------------------------------------------------------------------------------------------------------------------------

# 以redis镜像创建容器,然后启动
# 以下6个命令都只是创建出容器
# redis容器启动后的docker-entrypoint.sh脚本进程,启动了redis-server服务,因此不用-ti,启动redis容器就会夯住
docker create --name test1 redis             # 容器启动,维持后台运行
docker create --name test3 redis ps -A       # 容器启动后执行ps -A命令,命令一执行完,容器就停止了

docker create -ti --name test2 redis         # 容器启动,维持后台运行
docker create -ti --name test4 redis ps -A   # 容器启动后执行ps -A命令,命令一执行完,容器就停止了

docker create -ti --name test5 redis /bin/bash  # 容器启动后运行bash,因为有-it参数,运行bash的命令没有结束,容器就不会停止
docker create --name test6 redis /bin/bash      # 容器启动后运行bash,没有-it参数,执行bash后就终止了

# docker start 启动容器
test1、test2、test5, 启动后容器夯住了,维持后台运行
test3、test4、test6,启动后容器停止了

容器一直运行的原因

Docker 容器启动后,默认会把容器内部第一个进程,也就是pid=1的程序作为docker容器是否正在运行的依据。如果docker 容器pid=1进程挂了,那么docker容器便会直接退出。这样的话,如果我们在前台维持一个运行的进程,docker 容器就会一直处于运行的状态中。

centos前台跑的是/bin/bash, redis前台跑的是redis-server(通过docker-entrypoint.sh脚本),mysql前台跑的是mysqld,nginx前台跑的nginx

        -以后如果自己制作的镜像,运行起容器,必须有个可以夯住的前台进程
        -如果该进程结束,该容器也就结束了
        -比如 docker run -it --name=myredis redis 创建并启动容器,并且进入到redis
                 docker run -it --name=mycontainer centos:centos7 创建并启动容器,进入到一个纯净的centos7操作系统
             如果用exit退出bash窗口,就会结束bin/bash命令,并且该操作系统(容器)也就停止了

4.3 容器启动 – docker start

# 作用:
	将一个或多个处于创建状态或关闭状态的容器启动起来
    
# 命令格式:
	docker start [OPTIONS] CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	-a, --attach		将当前shell的 STDOUT/STDERR 连接到容器上
	-i, --interactive	将当前shell的 STDIN连接到容器上	
    
# 命令演示:
docker ps -a
docker start -a 65ebc
docker start test-container2

4.4 容器创建并启动 – docker run

# 作用:
	利用镜像创建并启动一个容器
    
# 命令格式:
	docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
    
# 命令参数(OPTIONS):查看更多
	-t, --tty           分配一个伪TTY,也就是分配虚拟终端,表示容器启动后会进入其命令行
    -i, --interactive   以交互模式运行容器,加入-t-i这两个参数,容器启动后会直接进入容器。分配一个伪终端
        --name          为容器起名,如果没有指定将会随机产生一个名称
	-d, --detach		创建一个守护进程在后台运行容器并打印出容器ID,不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进入容器
	--rm			    当容器退出运行后,自动删除容器
    
# 命令参数(COMMAND\ARG):
	COMMAND 表示容器启动后,需要在容器中执行的命令,如ps、ls 等命令
	ARG 表示执行 COMMAND 时需要提供的一些参数,如ps 命令的 aux、ls命令的-a等等
    
# 命令演示:
# 注意,docker run 镜像, 如果本地没有该镜像,会先pull最新版镜像,再执行docker run
docker run --name test1 centos:centos7                # 创建并启动test1,启动后容器就停止了
docker run --name test2 centos:centos7 /bin/bash      # 创建并启动test2,启动后容器就停止了
docker run -ti --name test3 centos:centos7            # 创建并启动test3,启动后运行/bin/bash交互(根路径下),exit退出后,容器就停止了 
docker run -ti --name test4 centos:centos7 /bin/bash  # 创建并启动test4,启动后运行/bin/bash交互(根路径下),exit退出后,容器就停止了 
docker run -ti --name test5 redis            # 创建并启动test5,启动后进入到redis前端,exit退出后,容器就停止了 
docker run -ti --name test6 redis /bin/bash  # 创建并启动test6,启动后运行/bin/bash交互(/data路径下),exit退出后,容器就停止了

docker run -d --name t1 centos:centos7    # 创建并启动t1,启动后容器就停止了
docker run -di --name t2 centos:centos7  # 创建并启动t2,启动后容器维持后台运行
docker run -d --name t3 redis             # 创建并启动t3,启动后容器维持后台运行
docker run -dti --name t4 redis           # 创建并启动t4,启动后容器维持后台运行

4.5 docker run 与 docker create + docker start

docker run    相当于 docker create + docker start –a      前台模式
docker run -d 相当于 docker create + docker start          后台模式

4.6 容器暂停 – docker pause

# 作用:
	暂停一个或多个处于运行状态的容器
    
# 命令格式:
	docker pause CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	无
    
# 命令演示
docker ps -a
docker pause test-container2
docker ps -a # 容器是Pause状态

4.7 容器取消暂停 – docker unpause

# 作用:
	取消一个或多个处于暂停状态的容器,恢复运行
    
# 命令格式:
	docker unpause CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	无	
    
# 命令演示:
docker unpause test-container2
docker ps -a # 处于运行状态

4.8 容器关闭 – docker stop

# 作用:
	关闭一个或多个处于暂停状态或者运行状态的容器
    
# 命令格式:
	docker stop [OPTIONS] CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	-t, --time int   关闭前,等待的时间,单位秒(默认 10s)	
    
# 命令演示:
docker stop -t 1 容器id

4.9 容器终止 – docker kill

# 作用:
	强制并立即关闭一个或多个处于暂停状态或者运行状态的容器
    
# 命令格式:
	docker kill [OPTIONS] CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	-s, --signal string   	指定发送给容器的关闭信号 (默认“KILL”信号)	
    
# 命令演示:
docker kill test-container2

4.10 docker stop和docker kill的区别

# 一 前提知识点:
    1 Linux其中两种终止进程的信号是:SIGTERM和SIGKILL
    2 SIGKILL信号:无条件终止进程信号。
    进程接收到该信号会立即终止,不进行清理和暂存工作。
    该信号不能被忽略、处理和阻塞,它向系统管理员提供了可以杀死任何进程的方法。
    3  SIGTERM信号:程序终结信号,可以由kill命令产生。
    与SIGKILL不同的是,SIGTERM信号可以被阻塞和终止,以便程序在退出前可以保存工作或清理临时文件等。

# 二 docker stop 会先发出SIGTERM信号给进程,告诉进程即将会被关闭。在-t指定的等待时间过了之后,将会立即发出SIGKILL信号,直接关闭容器。
# 三 docker kill 直接发出SIGKILL信号关闭容器。但也可以通过-s参数修改发出的信号。

# 四 因此会发现在docker stop的等过过程中,如果终止docker stop的执行,容器最终没有被关闭。而docker kill几乎是立刻发生,无法撤销。

# 五 此外还有些异常原因也会导致容器被关闭,比如docker daemon重启、容器内部进程运行发生错误等等“异常原因”。

4.11 容器重启 – docker restart

# 作用:
	重启一个或多个处于运行状态、暂停状态、关闭状态或者新建状态的容器
	该命令相当于stop和start命令的结合
    
# 命令格式:
	docker restart [OPTIONS] CONTAINER [CONTAINER...]
    
# 命令参数(OPTIONS):
	 -t, --time int   	重启前,等待的时间,单位秒(默认 10s) 
				        实则是关闭前等待的时间

4.12 容器删除 – docker container rm

# 作用:
	删除一个或多个容器
    
# 命令格式:
	docker container rm [OPTIONS] CONTAINER [CONTAINER...]
      或者 docker rm [OPTIONS] CONTAINER [CONTAINER...]
        
# 命令参数(OPTIONS):
	 -f, --force     		强行删除容器(会使用 SIGKILL信号) 
	 -v, --volumes   		同时删除绑定在容器上的数据卷	
        
# 命令演示
docker rm -f 容器id 容器名
docker rm 8379 7380 1023      # 可以放多个id,批量删除
docker rm `docker ps -a -q`   # 删除所有容器

 

5 容器信息查看

5.1 容器详细信息 – docker container inspect

多个容器互通(多个机器通信)的几种方式:

方式一:ip地址(局域网,默认网段172.17.0.x ),都连到一个网关172.17.255.255(宿主机虚拟出的网卡)。django项目连mysql容器,直接连容器ip。

方式二:端口映射(映射到宿主机,通过宿主机通信)

方式三:通过主机名

# 作用:
	查看本地一个或多个容器的详细信息
    
# 命令格式:
	docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
      或者 docker inspect [OPTIONS] CONTAINER [CONTAINER...]
        
# 命令参数(OPTIONS):	
	-f, --format string	利用特定Go语言的format格式输出结果
	-s, --size		显示总大小
    
# 命令演示
docker container inspect 容器id
docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器ID   # 仅查看ip地址

5.2 容器日志信息 – docker logs

# 作用:
	查看容器的日志信息
    
# 命令格式:
	docker logs [OPTIONS] CONTAINER
    
# 命令参数(OPTIONS):	
	    --details		    显示日志的额外信息
	-f, --follow            动态跟踪显示日志信息
	    --since string  	只显示某事时间节点之后的	
 	    --tail string       显示倒数的行数(默认全部)
	-t, --timestamps     	显示timestamps时间
	    --until string   	只显示某事时间节点之前的
        
# 注意:
	容器日志中记录的是容器主进程的输出STDOUT\STDERR

5.3 容器重命名 – docker rename

# 作用:
	修改容器的名称
# 命令格式:
	docker rename CONTAINER NEW_NAME
# 命令参数(OPTIONS):	
	无

 

6 容器运行时操作

6.1 容器连接 – docker attach

# 作用:
	将当前终端的STDIN、STDOUT、STDERR绑定到正在运行的容器的主进程上实现连接
# 命令格式:
	docker attach [OPTIONS] CONTAINER
# 命令参数(OPTIONS):	
	--no-stdin             	不绑定STDIN

6.2 容器中执行新命令 – docker exec

# 作用:
	在容器中运行一个命令
# 命令格式:
	docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
# 命令参数(OPTIONS):	
	-d, --detach               	后台运行命令
	-i, --interactive		    即使没连接容器,也将当前的STDIN绑定上
	-t, --tty                  	分配一个虚拟终端
	-w, --workdir string       	指定在容器中的工作目录
	-e, --env list             	设置容器中运行时的环境变量

# 以守护进程方式,启动了centos容器,后台运行
docker run -dti --name test1 centos:centos7
# 执行-ti 命令,运行bash,新建一个bash跟容器进行交互
docker exec -ti test1 /bin/bash

 进入容器的几种方式(并不是真进入)

第一种:docker exec -it 容器id /bin/bash  要后台运行中的容器才能利用bash做交互

-it 分配一个bash,如果是跑的centos容器,它只是类似于一个操作系统,通过查看它的进程,id1这个进程应该是系统sys,而容器里显示的是bash,也就是/bin/bash这个命令执行的进程。
exec真正的作用是在容器内执行命令,如docker exec 容器id ls   ==>执行ls命令
只不过正好 /bin/bash命令创建了bash,可以跟宿主机做交互

第二种:ssh连接(容器内部装sshd服务端,它会监听22端口)

问题:bash到底是t分配的,还是/bin/bash命令创建的?

 

7 其他操作

7.1 退出当前容器

exit 
 
docker run -it  # 创建并启动时直接进入容器,相当于一个终端在运行,exit退出后,这个终端就停止了,即容器停止了
docker run -d   # 创建并启动挂在后台运行,相当于一个终端在运行,再用exec连进去,又分配了一个伪终端,用exit退出,退出的是伪终端的bash,而容器并不会停止

7.2 文件拷贝

应用:如果项目就放在容器内跑,需要把项目依赖的文件拷贝到容器内

# 从宿主机拷贝到容器内部
docker cp 文件/目录 容器名/id:容器目录
docker cp lqz.txt 690f:/home         # 把lqz.txt文件拷贝到id为690f的容器的/home路径下

# 从容器内部拷贝到宿主机
docker cp 容器名/id:容器目录 目标目录
docker cp 690f:/home/lqz.txt /app    # 把id为690f的容器内home目录下的lqz.txt文件拷贝到宿主机的app目录下

7.3 目录挂载

我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。
创建容器 添加-v参数 后边为 宿主机目录:容器目录,例如:

docker run -di --name=mycentos -v /usr/local/myhtml:/usr/local/myhtml centos:centos7

 -v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的容器目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。因为容器删除后,目录里的数据就没有了,需要把数据映射到宿主机上保存。

如果你共享的是多级的目录,可能会出现权限不足的提示。这是因为CentOS7中的安全模块selinux把权限禁掉了,我们需要添加参数 --privileged=true 来解决挂载的目录没有权限的问题。

7.4 端口映射

应用:在云服务器下载redis,mysql镜像,跑起容器,跟宿主机做端口映射;进到redis容器内,存入数据-->本地客户端远程连6377端口,能够拿到容器内的数据,相当于通过云服务器(宿主机)访问到容器内6379端口的redis。

服务端根本不用安装redis或mysql,只用跑容器,客户端远程访问服务器-->映射到容器的端口。

# redis启动,docker exct 容器id pwd 查看进入路径,是在data目录下,centos进入是在根路径下
docker run -di -p 6377:6379 redis:latest
    
    
# 了解:/usr/local/bin/docker-entrypoint.sh
redis容器启动后的docker-entrypoint.sh进程(启动redis-server服务的进程),在这个路径下

-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口(如:把容器的80端口映射到宿主机的80端口,访问宿主机80端口就是访问容器的80端口)。可以使用多个-p做多个端口映射。

7.5 应用部署

1 MySQL部署

# 在容器内部署mysql
# -e表示环境变量,MYSQL_ROOT_PASSWORD 是root用户的登陆密码
# 它是往容器的环境变量(env)中加了key:val,即“MYSQL_ROOT_PASSWORD=123456”,mysql启动时去环境变量获取。这种方式比密码放到项目配置文件更安全。
# -p代表端口映射,格式为宿主机映射端口:容器运行端口

# 创建容器
docker run -di --name=mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

# 官方提供的,它多了-v目录挂载
docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

2 Nginx部署

# 在容器内部署Nginx,如果宿主机80端口被占用了,可以换一个,如8080:80
docker run -di --name=mynginx -p 80:80 nginx

 3 Redis部署

docker run -di --name=myredis -p 6377:6379 redis

操作步骤
-1 mkdir /reids  /redis/conf  /redis/data

-2 vim /redis/conf/redis.conf
# 宿主机配置文件
bind 0.0.0.0
daemonize NO       # 不以后台进行
protected-mode no  # 严格模式
requirepass 123456 # redis密码
        
-3 创建并运行容器
# 1、做了多个-v目录挂载,把redis配置文件和数据路径做了映射,redis配置了持久化,set数据会在data目录生成文件保存
# 2、redis-server /etc/redis/redis.conf 启动命令,以容器内部此路径下的配置文件启动
# 3、--appendonly yes 配置数据持久化
docker run -p 6379:6379 --name myredis -v /redis/conf/redis.conf:/etc/redis/redis.conf 
-v /redis/data:/data -di redis redis-server /etc/redis/redis.conf --appendonly yes

-4 本地window机器上远程连接到了docker里的redis
-5 cmd窗口下:
    redis-cli -h 10.0.0.200 -p 6379
-6 认证: 
    auth 123456
-7 写入数据:
    set name lqz
-8 保存数据:
    save或者是bgsave # redis容器配置文件没有配置数据持久化,重启容器后,数据就没有了
-9 在宿主机的/redis/data路径下就能看到一个文件
-10 不管重启多少次redis容器,数据都还在
-11 删除这个redis容器,宿主机上保存了配置文件和数据,新启的redis容器只要文件挂载到宿主机,就能用之前的配置和数据

 

8 环境变量相关

# 启动容器时,加入-e 参数
docker run -di --name=python -e name=zl -e age=18 python:3.6

# 进入容器
docker exec -ti python /bin/bash

# 查看环境变量
root@2ad974090bfd:/# env
name=zl
age=18 
存在于环境变量中

环境变量应用

# django项目,settings.py中配置mysql参数
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'luffy',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'luffy',
       # 'PASSWORD': 'Luffy123?',
        'PASSWORD':os.environ.get('MYSQL_ROOT_PASSWORD')  从环境变量中以MYSQL_ROOT_PASSWORD为key取值
        'CHARSET': 'utf8',
    }
}

# 启动django项目容器时,把mysql密码写入环境变量
docker run -di --name=mydjango -e MYSQL_ROOT_PASSWORD=Luffy123? django2.0:v1

 

posted @ 2022-10-16 00:16  不会钓鱼的猫  阅读(219)  评论(0编辑  收藏  举报