容器技术的核心就是通过对资源的限制和隔离把进程运行在一个沙盒中。并且这个沙盒可以被打包成容器镜像(Image),移植到另一台机器上可以直接运行,不需要任何的多余配置。其中docker是容器技术的事实标准。
最好只用于虚拟机或内网测试环境。如果机器有对外提供服务或以任何形式可以被互联网访问,请勿打开此端口,此端口会被利用从而导致容器被植入挖矿程序。
如果机器上的docker是使用二进制安装,启动dockerd的方式。可以直接在启动dockerd的时候
sudo dockerd -H unix:///var/run/docker.sock -H tcp://<addr>:<port>
#例如,我们想要可以从本机直接调用测试服务器上或虚拟机上的docker,可以设置
sudo dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
# 不能不设置 -H unix:///var/run/docker.sock 不然宿主机没法使用docker cli
一般docker.service的位置在 /usr/lib/systemd/system 或 /lib/systemd/system/
修改docker.service,在ExecStart=xxxxxx 后面添加 -H tcp://
#例如
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
然后执行命令
systemctl deamon-reload
systemctl restart docker
确保已经开放了docker的TCP端口后,并且IDEA安装了docker插件(idea utimate版都是预装的)。
进入IDEA Setting 的 Build,Execution,Deployment/docker,配置如下
将IP和端口设为docker宿主机的IP和开放的端口。
确保docker宿主机有ssh服务。在IDEA中进入Setting/Tools/SSH Configuration,配置如下
然后再进入IDEA Setting 的 Build,Execution,Deployment/docker,选择On SSH machine, 然后选中刚配置的docker宿主机的ssh即可。
首先IDEA上代码与容器内运行的代码版本一致。
IDEA在run/debug Configuration 添加一个Remote JVM Debug配置,如下。端口可以随便指定为一个可使用的端口
按提示将JVM添加到容器内进程的启动参数。
启动容器时添加debug端口到宿主机端口的映射。
Docker主要使用了Namespace实现了对容器资源的隔离,包括了
PID(进程编号)
UTS(主机信息)
network(网络)
user(用户权限)
mount(挂载信息)
IPC(进程间通信)
cgroups
正因为这些隔离,docker容器内的进程只能使用同一个namespace下的资源,只能感知同一个namespace下的其他进程。
Linux Cgroups技术可以限制进程对CPU、内存、IO设备等资源的使用。通过使用cgroups技术,docker engine可以限制每个容器所能使用的系统资源的大小。
用面向对象的思维可以把镜像(image)理解为类,容器(container)理解为对象。换一种说法可以将镜像理解为程序,容器理解为进程。
一个镜像可以在不同的宿主机(物理机或是虚拟机)上启动为容器,并且几乎不需要多余的配置。
镜像的本质是一个操作系统的文件系统(rootfs),而容器需要调用内核时实际上是使用了宿主机的内核。
docker image的rootfs是分层的,开发者可以在原有的image基础上添加需要的内容(即新的层)创建出新的image,这个步骤也可以简单的理解成面向对象中的继承。
容器技术和虚拟机的区别可见上图,主要差异在于虚拟机多了一整套由hypervisor虚拟化的硬件基础设施,并且包括完整的guest os(包括内核),而容器只包括rootfs。
因此不能认为容器是轻量级的虚拟机,容器的实质是宿主机的一个进程,只是通过了namespace、cgroups技术使这个进程和其他进程隔离并且拥有独立的文件系统。
所以理论上windows系统不能运行linux容器,因为windows没有linux内核,而容器需要共享宿主机内核。(实际上windows是可以使用WSL、Hyper-V来运行容器,但是WSL、Hyper-V运行linux容器的原理也是虚拟化了一套linux内核来运行linux容器)
注意!!!下文中的 [] 只是为了凸显内容,使用指令时不需要带[] 。 () 内的内容表示选择性内容。
只包括一些常用的docker指令,详细的用法可以登录 https://docs.docker.com/reference/ 查看docker官方参考手册或者使用指令时,docker [command] --help 查看指令的具体用法。
docker run -p [宿主机端口]:[容器端口] --name [容器名] \
-e TZ="Asia/Shanghai" \
-v /mydata/nginx/html:/usr/share/nginx/html \
-d nginx:1.17.0 \
--network [networkName] \
--restart=always
启动容器的基本命令就是docker run 镜像。另外docker提供了一系列的参数可以个性化的定义容器的各个参数,这些参数可以放在docker run 和 [image-name]之间,没有固定顺序。
docker start [containerName] | [containerId]
docker stop [containerName] | [containerId]
docker rm [containerName] | [containerId]
docker restart [containerName] | [containerId]
docker rename [containerName] | [containerId] [newName]
docker cp containerID:/usr/xxxx/xxxx/xxx.xml /usr/xxx/xxx
复制容器的/usr/xxxx/xxxx/xxx.xml 到外部的/usr/xxx/xxx
参数反过来就是复制容器外部的到容器里
docker exec -it --user [userName] [containerName] | [containerId] bin/bash
#可以根据指定容器的name或id进入对应容器 ,可以指定进入容器的用户,也可以不指定
docker exec -it --user [userName] [containerName] | [containerId] sh
#有的容器没有bin/bash,也许可以用sh
docker logs (-f) [containerName] | [containerId]
#加上-f的话可以查看容器动态产生的日志
docker inspect [containerName] | [containerId]
docker inspect --format '{{ .NetworkSettings.IPAddress }}' [containerName] | [containerId] #查看容器ip
docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' [containerName] | [containerId] #查看容器的MAC地址
docker inspect --format='{{.LogPath}}' [containerName] | [containerId] #查看容器日志路径
# 例如将容器的重启策略改为always
docker container update --restart=always [containerName] | [containerId]
docker stats [containerName] | [containerId]
docker top [containerName] | [containerId]
docker export -o [fileName] [containerName] | [containerId]
#例如 docker export -o ubuntu.tar ubuntu 即为将名为ubuntu的容器打包到当前目录的ubuntu.tar文件中
#容器打包指令会将容器的整个文件系统打包到指令文件,可以使用docker import命令将文件导入成docker镜像
docker image ls
docker images
docker pull [imageName]:[tag]
#不指定【tag】,默认为latest
docker image rm [imageName]
docker rmi [imageName]
docker load -i [fileName] #例如 docker load -o ubuntu.tar
docker import [fileName] [imageName]:[imageTag] #例如 docker import ubuntu.tar ubuntu:18
#区别在于docker load无法重命名,并且只能从文件导入。 docker import 可以重命名并且支持从url导入
docker tag [imageName]:[imageTag] [newImageName]:[newImageTag]
docker save -o [fileName] [imageName]
docker push [imageName]
docker image prune
#这个指令会删除 imagename或tag为空的镜像,使用时要谨慎。
docker system df
docker system prune
#会清理关闭的容器、虚无镜像和未使用的网络。请谨慎使用!
docker login (-u [username]) (-p [passwd]) [server]
docker logout [server]
Docker使用定义Dockerfile文件的方式显示声明镜像,Dockerfile是由一行行指令组成的文件。声明Dockerfile后,使用docker指令 docker build 打包镜像。
docker build (-t) [imageName]:[imageTag] .
#注意最后有一个点 '.' ,代表以当前目录为上下文。当前目录必须是dockerfile所在的目录
指定容器所依赖度的基础镜像
FROM xxxx
将当前目录下的文件复制到容器中,如果容量目录不存在则会创建该目录
ADD [文件、目录] [容器目录]
与ADD命令基本相同,如果容量目录不存在则会创建该目录
COPY [文件、目录] [容器目录]
RUN命令在构建镜像时执行,一般是下载一些程序到docker。
RUN
ENTRYPOINT命令在容器启动时执行,一般用来指定启动应用的命令。可以在容器启动时被替换
ENTRYPOINT
docker run 时执行的默认操作,可以在容器启动时被替换
CMD
指定容器的默认环境变量,可以在容器启动时再添加别的环境变量也可以替换原有的环境变量的值
ENV [key]=[value]
ENV [key] [value]
通知 Docker 容器在运行时侦听指定的网络端口,可以指定tcp或udp协议,如果不指定默认为tcp。
EXPOSE的意义主要在于声明,不添加EXPOSE依然可以建立容器与宿主机的端口映射。
最主要的区别在于如果声明了EXPOSE,并且运行时映射了该端口到宿主机的映射,可以从宿主机直接访问容器端口。
EXPOSE [port]/[protocol]
声明镜像的元数据信息。可以用于声明此镜像维护者的信息
LABEL author="henry"