Docker 基础介绍
docker, linux, servers
docker, linux, servers
Docker provides the ability to package and run an application in a loosely isolated environment called a container. The isolation and security allow you to run many containers simultaneously on a given host. Containers are lightweight and contain everything needed to run the application, so you do not need to rely on what is currently installed on the host. You can easily share containers while you work, and be sure that everyone you share with gets the same container that works in the same way.
传统项目开发完成,发布时需要在每台电脑上配置环境。而环境配置是很麻烦的,有些环境不能跨平台。
docker 的出现是为了解决软件开发后,发布到线上时需要重新部署整个环境的问题。将 jar包 与环境一起打包做成镜像,发布时只需下载镜像并运行即可。
docker容器与容器之间相互隔离,可以在一台电脑上运行多个而不会相互影响。
官方文档 :https://docs.docker.com/
镜像地址 :https://hub.docker.com/
镜像(images):
容器(container):
仓库(repository):
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# https://download.docker.com/linux/centos/docker-ce.repo
yum makecache fast
sudo yum install docker-ce docker-ce-cli containerd.io
# ce 指社区版, ee 指企业版
安装其它版本 docker
查看其它版本的 docker
yum list docker-ce --showduplicates | sort -r
安装其它版本的 docker
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
启动docker
sudo systemctl start docker
docker version
sudo docker run hello-world

docker images
sudo yum remove docker-ce docker-ce-cli containerd.io
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
docker images

/var/lib/docker 目录下。从网络中查找需要的镜像
docker search 镜像名称

NAME:仓库名称
DESCRIPTION:镜像描述
STARS:用户评价,反应一个镜像的受欢迎程度
OFFICIAL:是否官方
AUTOMATED:自动构建,表示该镜像由Docker Hub自动构建流程创建的
官网地址 :https://hub.docker.com
Mirror与Private Registry的区别:
拉取镜像
docker pull mysql:5.7
# dokcer pull 镜像名:版本号,若不加版本号,则默认使用 latest,最新版
编辑文件:
vim /etc/docker/daemon.json
在文件中输入内容
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}

重启docker服务
systemctl restart docker
docker rmi 指定镜像
docker rmi 名称:tag
# 删除全部镜像
docker rmi -f $(docker images -aq)
查看当前正在运行的容器
docker ps
# 查看当前正在运行的容器
# docker ps --help 查看ps的所有选项

查看所有的容器【常用】,包括运行中的与停止的
docker ps -a
查看最后一次运行的容器
docker ps -l
docker run(创建且运行 create+st) (create)
常用参数说明
| 参数名 | 说明 |
|---|---|
-i | 表示容器运行 |
-t | 表示容器启动后会进入其命令行。加入这个参数后,容器创建就能登录进去。 |
--name | 为创建的容器命名 |
-v | 表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件映射 |
-d | 在run后面加上 -d 参数,则容器可以在后台运行 |
-p | 表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。 |
--restart always # 容器会随着 docker 的启动而启动
docker run -it --name=mycentos centos:7 /bin/bash
# 创建后会自动进入容器中

退出当前容器
exit
创建一个守护式容器:如果对于一个需要长期运行运行的容器,我们可以创建一个守护式容器命令
docker run -i -d --name=mycentos2 centos:7
登录守护式容器
docker exec -i -t 容器名/容器id /bin/bash
# 进入容器,开启一个新终端
docker attach 容器id
# 进入容器,不会启动新的终端,而是进入之前开启的终端

停止正在运行的容器
docker stop 容器名

启动已存在的容器
docker start 容器名

重启容器
docker restart 容器名/容器id
docker cp source target
# 容器中地址:容器id:/路径
# source 源文件地址,可以是容器中或宿主中
# targer 目标地址,容器中或宿主中
在创建容器时,将宿主机的目录与容器内的目录进行映射,这样就可以通过修改宿主机某个目录的文件从而去影响容器中所对应的目录。
创建容器,并挂载宿主机目录到容器中的目录下:
docker run -i -d -v /usr/local/myhtml:/user/local/myhtml --name=mycentos3 centos:7
# 宿主目录:容器目录
如果你共享的是多级的目录,可能会出现权限不足的提示。这是因为CentOS7中的安全模块selinux把权限禁掉了,我们需要添加参数--privileged=true来解决挂载的目录没有权限的问题。
docker run -di --privileged=true -v /root/test:/usr/local/test --name=mycentos4 centos:7
查看容器运行的各种数据
docker inspect 容器名
也可以直接执行查看IP地址
docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名

删除指定容器:只能删除已经停止的
docker rm 容器名/容器id
删除所有容器【慎用】
docker rm ${docker ps -aq)
docker logs 容器名/容器id
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、库、环境变量和配置文件等。
所有的应用,直接打包docker镜像,就可以直接跑起来。
UnionFS(联合文件系统)
UnionFS:Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。
Docker镜像实际上是由一层一层的文件系统组成的。
Boots
拉取镜像
docker pull mysql:5.7.35
创建 mysql 容器
docker run -i -d --name=mysql -p 13306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.35
-p 代表端口映射:宿主端口:容器运行端口-e 代表给容器添加环境变量。 MYSQL_ROOT_PASSWORD 是 root 用户登录密码,严格区分大小写进入MySql容器
docker exece -i -t mysql /bin/bash
登录 MySql
mysql -u root -p

授权远程登录
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
进行远程登录mysql即可
拉取 tomcat 镜像
docker pull tomcat:7-jre8
创建tomcat容器
docker run -di --name=tomcat -p 9100:8080 tomcat:7-jre8
测试tomcat
拉取Nginx镜像
docker pull nginx
创建 nginx 容器
docker run -di --name=pinyougou_nginx -p 80:80 nginx
测试
拉取Redis镜像
docker pull redis
创建Redis容器
docker run -di --name=pinyougou_redis -p 6379:6379 redis
测试
docker commit -m='提交者的描述信息' -a='作者' 容器id 目标镜像名:tag
docker save -o 要保存的文件名.tar 镜像名称:tag/镜像id
# -o 表示输出到文件
docker load -i xxx.tar
# -i 输入的文件
Docker的数据都直接存储在 Docker之中,若docker被删除则数据丢失。
容器数据卷:容器之间的一个数据共享技术。Docker 容器中产生的数据,同步到本地。即目录的挂载。
使用命令直接挂载 -v
docker run -it -v /home/test:/home centos:7 /bin/bash
# 前边的目录为宿主机的目录
# 后边的目录为容器中的目录
# 会将宿主机中的该目录与容器中的该目录进行同步,双向绑定
当挂载后将容器删除,宿主机中文件仍然存在。
具名和匿名
具名:-v 容器内路径,设置容器内卷名
docker run -it -v named:/etc/local centos:7
匿名:-v 之后直接写容器内路径而不写宿主机地址
docker volume ls
# 查看所有 卷 的情况
所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volume/xxx,数据都在其目录下的 _data 中
具名与匿名区分:
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /容器外路径:容器内路径 # 指定路径挂载
# 通过 -v 容器内路径,ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 读写
docker run -d -p --name centos01 -v named:/etc/centos:ro centos:7
docker run -d -p --name centos01 -v named:/etc/centos:rw centos:7
# 一旦设置了容器权限,容器挂载出来的内容就有限定了
# ro 容器内只能读,只有宿主机中才能修改
Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile从FROM命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像.
创建镜像步骤:
# 表示注释| 命令 | 作用 |
|---|---|
FROM image_name:tag | 定义了使用哪个基础镜像启动构建流程 |
MAINTAINER user_name | 声明镜像的创建者 |
ENV key value | 设置环境变量,可以设置多条 |
RUN command | 启动时运行的指令,可以写多条 |
ADD source_dir/file dest_dir/file | 将宿主机的文件复制到容器内,会自动解压缩 |
COPY source_dir/file dest_dir/file | 与ADD相似,只是不会自动解压 |
WORKDIR path_dir | 设置工作目录 |
EXPOSE port1 port2 | 用来指定端口,使容器内的应用可以通过端口和外界交互 |
CMD argument | 在容器启动时使用,只有最后一个生效,会被 docker run 后的参数覆盖 |
ENTRYPOINT argument | 和CMD类似,追加指令,但是不会被 docker run 后的内容覆盖 |
VOLUME | 将本地文件或者其它容器的文件挂载到容器中 |
FROM scratch # 最基本的
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM debian:buster-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql
RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*
# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.12
RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates wget; \
rm -rf /var/lib/apt/lists/*; \
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
chmod +x /usr/local/bin/gosu; \
gosu --version; \
gosu nobody true
RUN mkdir /docker-entrypoint-initdb.d
RUN apt-get update && apt-get install -y --no-install-recommends \
# for MYSQL_RANDOM_ROOT_PASSWORD
pwgen \
# for mysql_ssl_rsa_setup
openssl \
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
perl \
# install "xz-utils" for .sql.xz docker-entrypoint-initdb.d files
xz-utils \
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \
# gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
key='A4A9406876FCBD3C456770C88C718D3B5072E1F5'; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
apt-key list > /dev/null
ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.35-1debian10
RUN echo 'deb http://repo.mysql.com/apt/debian/ buster mysql-5.7' > /etc/apt/sources.list.d/mysql.list
# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN { \
echo mysql-community-server mysql-community-server/data-dir select ''; \
echo mysql-community-server mysql-community-server/root-pass password ''; \
echo mysql-community-server mysql-community-server/re-root-pass password ''; \
echo mysql-community-server mysql-community-server/remove-test-db select false; \
} | debconf-set-selections \
&& apt-get update \
&& apt-get install -y \
mysql-server="${MYSQL_VERSION}" \
# comment out a few problematic configuration values
&& find /etc/mysql/ -name '*.cnf' -print0 \
| xargs -0 grep -lZE '^(bind-address|log)' \
| xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \
# don't reverse lookup hostnames, they are usually another container
&& echo '[mysqld]\nskip-host-cache\nskip-name-resolve' > /etc/mysql/conf.d/docker.cnf \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \
&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
&& chmod 1777 /var/run/mysqld /var/lib/mysql
VOLUME /var/lib/mysql
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
创建 demo 目录并创建 Dockerfile 文件
mkdir /home/dockerfile
cd /home/dockerfile
vim Dockerfile
在 Dockerfile 中输入内容
FROM centos:7
MAINTAINER zhboom<suffergoof@gmail.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
在当前目录中创建自定义镜像,最后的 . 不能被省略
docker build -f Dockerfile -t mycentos:1.0 .
# -f 指定要构建的文件,默认为 Dockerfile
# -t 生成的对象文件



测试运行
docker run -i -t mycentos:1.0

查看本地进行的变更历史
docekr history $image_name:tag

[root@zhboom dockerfile]# dockerfile-cmd-test
FROM centos:7.0
CMD ["ls", "-a"]
# 构建镜像
[root@zhboom dockerfile]# docker build -f docker-cmd-test -t cmdtest .
# run 运行
[root@zhboom dockerfile]# docker run cmdtest
# 正常展示文件列表,执行了 ls -a
[root@zhboom dockerfile]# docker run cmdtest -l
ERROR
# 因为 -l 命令替换了 ls -a ,而系统不识别 -l 命令,因此会报错
[root@zhboom dockerfile]# dockerfile-cmd-test
FROM centos:7.0
ENTRYPOINT ["ls", "-a"]
# 构建镜像
[root@zhboom dockerfile]# docker build -f docker-cmd-test -t cmdtest .
# run 运行
[root@zhboom dockerfile]# docker run cmdtest
# 正常展示文件列表,执行了 ls -a
[root@zhboom dockerfile]# docker run cmdtest -l
# 展示文件列表及其详细信息
准备工作
FROM centos:7
MAINTAINER zhboom<suffergoof@gmail.com>
COPY readme.txt /usr/local/readme.txt
ADD OpenJDK8U-jdk_x64_linux_hotspot_8u302b08.tar.gz /usr/local/
ADD apache-tomcat-9.0.53.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk8u302-b08
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.53
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.53
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.53/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.53/bin/logs/catalin
a.out
docker build -t diytomcat .


运行容器实例,并挂载路径
docker run -d -p 18080:8080 --name=zhboomtomcat \
-v /home/zhboom/build/tomcat/test:/usr/local/apache-tomcat-9.0.53/webapps\test \
-v/home/zhboom/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.53/logs diytomcat


查看历史信息
docker history diytomcat:latest

登录自己的 Docker Hub 账号
docker login -u username # 回车
# 输入密码
Login Success # 表示登录成功
提交镜像
# 重命名镜像
docker tag 镜像id|镜像名 username/diytomcat:1.0
# 发布到 Docker Hub
docker push username/diytomcat:1.0
先清空环境
# 删除所有容器
docker rm -f $(docker ps -aq)
# 删除所有镜像
docker rmi -f $(docker images -aq)
获取当前 ip 地址
ip addr

# 启动一个 tomcat 容器
docker run -id -P --name tomcat01 tomcat:9.0
# -P 大写P,随机分配端口
# 查看容器的ip
# docker exec -id tomcat01 ip addr 新版的tomcat容器中不带 ip 指令
docker inspect --format='{{.NetworkSettings.IPAddress}}' tomcat01
172.17.0.2
测试宿主与容器能否联通
ping 172.17.0.2

我们每启动一个 docker 容器,docker 就会给 docker容器分配一个 ip,只要安装了 docker,就会有一个网卡 docker0。
docker0 使用了桥接模式,使用了 veth-pair 技术
veth-pair : 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连。通常利用 veth-pair 充当一个桥梁,用于连接各种虚拟网络设备。
解决问题:两个容器之间无法通过容器名相互连通。需要通过ip地址才能连接,但是每次容器启动ip不能保持一致。
--link
docker run -d -p --name tomcat03 --link tomcat02 tomcat
# tomcat02为之前已存在并运行中的容器名
# 使用 --link 会在 tomcat03 存储 tomcat02 的链接
# 此时 tomcat03可以直接 ping 通 tomcat02
docker exec -it tomcat03 ping tomcat02
# 但反过来却不通,需要在 tomcat02 中配置 tomcat03
docker exec -it tomcat02ping tomcat03
查看所有docker网络
docker network ls

docker run -id -p --name tomcat01 --net bridge tomcat:9.0
# 之前启动,其实默认就是上面的语句,自带 --net bridge。docker0
docker run -id -p --name tomcat01 tomcat:9.0
# docker0: 默认,但是不能通过容器名链接

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 创建了一个网络名为 mynet
# driver: 该网络使用网桥模式,桥接
# subnet: 子网为 192.168.0.0/16,B类网络。
# gateway: 网关为 192.168.0.1

docker run -id -P --name tomcat02 --net mynet tomcat:9.0
docker run -id -P --name tomcat02 --net mynet tomcat:9.0
通过自定义网络创建的容器可以直接通过容器名互联
日志还会继续,欢迎常来。
返回首页