docker
Docker
docker优点:
启动速度很快
运行需要的内存占用小
可移植性很好:
比如我们做了一个web app,按照以前的做法,自然是先写代码,再测试,然后在实际的环境中去运行。然后实际的环境与测试的环境并不一致,这就会出现很多问题。而docker不同,它把代码,运行的环境,依赖这些统统封装好了,打包为一个image,在实际的环境中只要安装docker,跑一下这个image就可以了,不会存在环境不同,缺少依赖等等问题。这就好像运行一个独立的虚拟机一样,但是比虚拟机更好。
docker vs virtual machine
docker的运行速度与大小比虚拟机都小很多,那么他们之间的差异是怎么形成的?
docker与virtual machine的对比:
virtualmachine:硬件+hypev技术+os操作系统(linux+software)
docker:硬件+(共享)系统linux内核+docker+software(不同os所需的lib等+software)
总结一下,虚拟机使用了hyperv技术,让不同的操作系统运行在虚拟机上。而docker则是共享正在运行的系统的linux内核,然后在docker上运行不同docker所需的软件,环境配置,库,依赖等。
所以虚拟机运行的是独立的操作系统,docker则仅仅是加载所需的库,依赖等,所以大小不同。至于启动速度也很好理解了,虚拟机需要启动一个独立的操作系统,需要的时间长;docker则不同,它依赖的就是系统本身的linux内核,等于说早就已经启动,只需要加载必要的software和依赖等就行了。
所以docker最好是运行在linux上,因为它要共享linux的内核,如果安装在windows上的话,那么docker就需要运行虚拟机,然后在虚拟机上运行docker,那么就体现不出docker的优势了。
如果虚拟机运行的是一个完整的操作系统,那么docker就像是运行一个软件,只不过还需要加载一个不同的依赖和环境而已。弄明白了docker的工作原理,只想说I love docker
image and docker container
image镜像是官方早就已经做好的,我们只需要下载下来,启动docker,然后运行这个image就行了。那么image运行的状态就叫docker container容器。
docker安装
树莓派上面叫docker.io:
1 | sudo apt-get install docker.io |
archlinux上面:
1 | sudo pacman -S docker |
查看版本:
1 | sudo docker version |
添加国内镜像地址
1 | sudo vim /etc/docker/daemon.json |
1 | { |
启动docker服务
1 | sudo systemctl start docker |
搜索需要的image
1 | sudo docker search image_name |
下载image
1 | sudo docker pull image_name |
或者
1 | sudo docker run image_name |
这种是直接运行一个container容器,如果还没有安装过,那么会自动下载
查看已下载的images
1 | sudo docker images |
查看镜像信息
1 | sudo docker inspect images |
删除已下载images
1 | sudo docker rmi <IMAGE ID> |
运行container
两种方式:
attach:在终端中运行,可以看到container的运行信息
1
sudo docker run image_name:tag
其中tag为lastest时可以省略,如果为其它tag则必须指定出来
detach:类似于放到后台运行
1
2
3
4sudo docker run -d image_name
sudo docker run -d --name NAMES image_name # 指定运行container名字
eg:
sudo docker run -d --name my-nginx nginx
查看正在运行的container
1 | sudo docker ps |
停止运行的container
1 | sudo docker stop <CONTAINER ID>/NAMES |
重启容器
1 | sudo docker restart <CONTAINER ID>/NAMES |
查看所有的container
1 | sudo docker ps -a |
删除已有container
1 | sudo docker rm <CONTAINER ID>/NAMES |
删除运行container中无用的数据(包括images)
1 | sudo docker system prune |
删除所有无用数据,包括停止的container
1 | sudo docker system prune -a |
删除所有docker数据
docker数据默认存储在/var/lib/docker
中
1 | sudo rm -R /var/lib/docker |
container运行条件
容器能够运行一定是启动的这个container上面有程序,服务正在运行。如果没有(比如运行一个linux系统),或者这个程序停止崩溃了,那么这个container就自动退出了。
1 | docker run ubuntu |
container会自动退出,因为没有进程,或者程序运行,仅仅是一个Ubuntu系统。
如果需要它启动呢?
1 | docker run ubuntu sleep 100 |
进入容器运行命令
类似ssh远程登录container,并指定使用bash来作为解释的shell
1 | docker exec -it container_name /bin/bash |
-i
交互模式interactive
-t
模拟tty登录
指定宿主机与容器的端口映射
-p
publish,发布的端口port。如果不指定则只能从容器内部访问,发布端口会将容器端口映射到主机端口,实现外部访问。
1 | sudo docker run -d --name NAMES -p host_port:container_port image_name |
指定了访问宿主机的8080端口时,自动映射到容器的80端口
容器的修改保存
如果不保存,那么对容器的修改不会持久化,也就是说修改不会保存到镜像中,只会保存在运行的container中。如果重新使用镜像生成容器,那么修改就没有了。
所以我们需要对修改进行提交,tag可以不写,默认为latest,如果写了,那么在创建容器时必须指定tag。
1 | sudo docker commit -a "author" -m "message" <CONTAINER ID>/NAMES new_image_name:tag |
1 | eg: |
所以说,对容器修改的提交,就会创建一个新的镜像,所有的修改都会保存在新的镜像中。
文件、目录挂载
将宿主机中的文件挂载到容器中,挂载之后对宿主机中文件的修改,会反应到容器中,反之也会。共享数据实现了数据的持久化,同时方便本地的开发。
1 | sudo docker run -d --name NAMES -p host_port:container_port -v host_file:container_file image_name |
发现修改第二次修改之后容器中并没有发生改变,所有需要重启一下容器就正常了
1 | sudo docker restart nginx |
将容器中的文件复制到本地
1 | sudo docker cp NAMES:/containcer_file /host_file |
将本地文件复制到容器中
1 | sudo docker cp /host_file NAMES:/container_file |
mysql容器的建立
设置root密码
-e MYSQL_ROOT_PASSWORD=my-secret-pw
数据同步备份
-v /my/own/datadir:/var/lib/mysql
获取远程权限(mysql8.0之后需要)
alter user 'root'@'%' identified with mysql_native_password by '123456';
查看权限
select host,user,authentication_string from user;
端口映射
-p host_port:container_port
1 | sudo docker run -d --name mysql -v /home/narcissus/Data/dumpfile:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql |
然后就可以通过软件来连接docker中的mysql数据库了:
主机填写:localhost
或者127.0.0.1
端口为映射的主机地址:3306
容器互联
--link 要被连接的容器名:在容器中的新别名
使用nginx去连接mysql数据库
1 | sudo docker run -d --name nginx -p 80:80 --link mysql:mysql nginx |
这样nginx就连接了mysql
自己构建镜像
前面已经写过如何保存修改镜像并生成新的镜像,指的是在container的基础上对镜像的修改。这里的构建镜像指的是如何基于原始镜像构建自己所需功能的基础镜像,也可以简单说是下载一些需要的软件,修改一些端口配置文件等等,来形成自己的个性化配置镜像。本来也可以使用container来一步一步的操作,但是dockerfile提供了自动化配置。
编辑dockerfile文件,通过文件来构建镜像,dockerfile分为四个部分
基础镜像信息
如果本地有image那么会使用本地的,如果没有会自动下载
1
2
3from image_name:tag # tag为latest时可以省略
eg:
from nginx维护者信息
1
2
3maintainer name
eg:
maintainer lanzhan镜像操作指令
run
run后面的command为平常使用的shell命令
1
2
3run command
eg:
run apt-get install sqlite3如果需要传参
1
2
3run ['executable','param1','param2']
eg:
run ['./somefile.sh','66','/home/']每一个指令都会在docker上新建一层,形成当前最新的dockerimage,所以应该把指令写到一条中
\
的作用为换行1
2
3run apt-get install sqlite3 &&\
['./somefile.sh','66','/home/'] &&\
echo "there command in a run instruct"这样只会新建一层镜像。
copy
和add
用于复制本机文件到docker中,在docker构建镜像时,会将要复制的文件所在目录下的所有文件先tar打包,然后发送给docker引擎,所以dockerfile所在的目录应该不包含没用的数据,如果有需要复制的文件,那么就把文件复制到dockerfile所在的目录下,而不要放一些没用的数据。
1 | copy 本机文件 容器中路径 |
copy和add功能类似,不同点:add会将tar类型的自动解压,同时可以访问网络,copy则不行。
cmd
只有最后一条起作用
与run类似,但是运行时间点不同,run是在docker build时运行(构建镜像),cmd则是在docker run时运行(启动容器)
作用是为container指定默认启动起来后运行的程序,不过如果自己指定了,那么会覆盖它。例如
1 | sudo docker run -it --name mysql /bin/bash |
entrypoint
只有最后一条起作用
与run类似,不同点在于不会被docker run中指定的命令覆盖
label
为镜像添加标识
1 | label key=value key=value |
env
为docker设置环境变量,后面可以使用$key
来引用变量
1 | env key value |
arg
与env类似,不同点在于设置的变量仅对dockerfile有效(构建镜像时),对docker镜像没效
volume
设置默认挂载目录文件等,指定持久化目录
1 | volume /location1 /location2 |
expose
指定要开放的端口,仅仅是告诉外部开放了那些端口可用,只用通过端口映射才真正可以从外部访问docker。
1 | expose port1 port2 port3 |
workdir
指定的目录要提前创建好,在每次构建新的一层中它会一直存在。
1 | workdir /location |
user
为后续命令切换用户(和用户组)
1 | user user_name |
healthcheck
指定某个程序来监控docker运行状态
1 | healthcheck option cmd command |
onbuild
当下次构建镜像时,如果以这个新构建的镜像为基础镜像时,会执行
1 | onbuild command |
容器启动执行指令
cmd
和entrypoint
构建镜像
点表示在当前目录下,tag可以不写默认为lastest
1 | docker build -t image_name:tag . |
使用archlinux构建mariadb数据库
archlinux中mariadb代替了mysql
- 新建dockerfile文件
1 | mkdir /home/narcissus/Data/docker |
- dockerfile文件
1 | from archlinux/base |
不使用cmd而使用entrypoint的原因是cmd命令会被启动容器时的命令覆盖
start.sh文件
由于entrypoint只能执行一条指令,所以启动mysql的命令需要写到文件中。通过执行脚步来运行。
本来打算使用systemd去启动,但是没有这个软件,而且安装了不知道怎么启用systemd,还有为了不让镜像太大
1 | !/bin/bash |
- 运行dockerfile
1 | sudo docker build -t mariadb . |
- 新建container
1 | sudo docker run -d --name mariadb -p 3306:3306 mariadb |
- 进入容器修改密码,设置远程登录权限
1 | sudo docker exec -it mariadb /bin/bash |
1 | mysql -uroot -p |