Docker介绍

Docker介绍

1、Docker是什么?

docker为什么会这么火呢?这就涉及到平时开发人员的工作,开发人员在本地可运行的项目,部署到服务器上后无法运行,可能是某些环境参数不对等问题。现在项目的部署通常是集群的方式,如果集群数量太多,运维人员需要一个个节点去部署配置,工作量太大。

总结就是一句话:解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。


2、Docker能干嘛?

​ 相信大家都用过VMware来运行虚拟机。下载CentOS时通常会下载一个将近4g的镜像文件。这个镜像文件中包含了一个完整的操作系统,包括内核及各类硬件的虚拟化。

​ 而Docker容器虚拟化与宿主机使用的是同一个内核,也无需对各类硬件资源进行虚拟化,由于与宿主机共享内核,所以Docker容器比虚拟机能更快启动,通常只需要一两秒,而传统虚拟机则需要更多的时间,可能需要花上几分钟。

​ Docker拥有一次构建、随处运行的强大功能,有点像Java,Docker将开发者提供的项目构建完后生成一个镜像文件,这个镜像文件即可以运行,然后生成一个容器。这种功能使Docker用更快速的应用交付和部署,更便捷的升级和扩缩容,更简单的系统运维,更高效的计算资源利用等优点。正是这些优点让新浪、美团、蘑菇街等互联网企业都在使用。


3、Docker常用命令

帮助命令 :docker --help

使用此命令可以查询docker中所有命令,属于必备命令

3.1 Docker镜像命令

docker images [options] 列出本地主机上的镜像

options选项 作用
-a 列出本地所有的镜像(含中间映像层)
-q 只显示镜像ID
--digest 显示镜像的摘要信息
--no-trunc 显示完整的镜像信息

docker search [options] 镜像名字

options选项 作用
--automated 只列出 automated build类型的镜像
-s 列出收藏数不小于指定值的镜像
--no-trunc 显示完整的镜像描述

docker pull 镜像名字[:TAG]

若不写TAG默认为latest

docker rmi [options]

options选项 作用
(不填)+ 镜像名字ID 删除镜像
-f + 镜像名ID 删除单个镜像
-f + 镜像名1:TAG + 镜像名2:TAG 删除指定的多个镜像
-f + $(docker images -qa) 删除全部镜像

3.2 Docker容器命令

需要先有镜像才能创建容器 故先下载CentOS镜像演示 docker pull centos

命令 作用
docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 新建并启动容器 如:docker run -it image 镜像名ID 新建并以交互式方式启动容器
docker ps [OPTIONS] 列出当前所有正在运行的容器
exit 停止容器并退出
ctrl+p+q 容器不停止并退出
docker start 容器ID或容器名 启动容器
docker restart 容器ID或者容器名 重启容器
docker stop 容器id或者容器名 停止容器(类似电脑桌面点关机)
docker kill 容器id或者容器名 强行停止容器(类似于电脑拔电源)
docker rm 容器id 删除已停止的容器
docker rm -f $(docker ps -a -q) 一次性删除多个容器
先docker ps -a -q 再 xargs docker rm 一次性删除多个容器

重点

命令 作用
docker run -d 容器名 守护式方式启动容器
docker logs -f -t --tail 容器ID -t 加入时间戳 -f 跟随最新的日志打印 --tail 数字 显示最后多少条
docker top 容器ID 查看容器内运行的进程
docker inspect 容器ID 查看容器内部细节
docker exec -it 容器ID /bin/bash 进入正在运行的容器并以命令行交互(在容器中打开新的终端,并且可以启动新的进程)
docker attach 容器ID 重新进入容器(直接进入容器启动命令的终端,不会启动新进程)
docker cp 容器ID:容器内路径 目的主机路径 从容器内拷贝文件到主机上

4、Docker镜像

4.1 镜像是什么

​ 镜像使一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

4.2 联合文件系统(UnionFS)

​ Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同事可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有的底层文件和目录。

4.3 为什么要使用分层镜像

​ 最大的一个好处:共享资源

比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务,而且镜像的每一层都可以被共享。

4.4 镜像的特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

4.5 Docker镜像Commit操作

docker commit 提交容器副本使之成为一个新的镜像;

docker commit -m=“提交的描述信息” -a="作者" 容器ID要创建的目标镜像名:[标签名]

若改动后commit新生成的镜像会是改动后的镜像,


5、 Docker容器数据卷

5.1 容器数据卷是什么?

​ 前面说到Docker是将应用和环境打包成一个镜像,那容器中的数据怎么办呢,如果数据都放在容器中,当容器删除时,我们的数据就会丢失。这时候容器数据卷就出现了。

​ 容器数据卷的作用就是实现数据的持久化,将容器中的数据同步到主机上,同时也能实现容器间的继承和容器间共享数据。

5.2 数据卷添加方式

5.2.1 直接命令添加

​ docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

数据卷挂载成功后,容器内的指定目录下和宿主机指定目录下就会实现数据共享,在任意处进行修改,在另一方的目录下会有相同修改。即便容器停止退出后,主机再次修改数据,重新启动容器后,容器内部的数据也是同步的。

​ docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名 (添加后设置容器针对该目录的权限为只读)

5.2.2 DockerFile添加

1、编写一个dockerFile脚本

2、构建该脚本(一层层构建成新的镜像)

3、新生成的镜像运行后会自动 绑定dockerFile脚本中指定的目录(与命令行方式相比)

Docker执行DockerFile的大致流程

1、docker从基础镜像运行一个容器;

2、执行一条指令并对容器做出修改;

3、执行类似docker commit的操作提交一个新的镜像层;

4、docker再基于刚提交的镜像运行一个新容器

5、执行dockerFile中的下一条指令直到所有指令都执行完成

从应用软件的角度来看,DockerFile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

DockerFile是软件的原材料;

Docker镜像是软件的交付品;

Docker容器可以认为是软件的运行态。

DockerFile面向开发,Docker镜像成为交付标准,Docker容器则设计部署与运维,三者缺一不可,合力充当Docker体系的基石

1、DockerFile,需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容包括执行代码或者文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

2、Docker镜像,在用DockerFile定义一个文件之后,docker build时会产生一个Docker镜像,当运行Docker镜像时,会真正开始提供服务;

3、Docker容器,容器是直接提供服务的。


6、DockerFile解析

6.1 保留字指令

如下代码是centos6.8的dockerfile文件

FROM scratch
MAINTAINER The CentOS Project <cloud-ops@centos.org>
ADD c68-docker.tar.xz /
LABEL name="CentOS Base Image" \
    vendor="CentOS" \
    license="GPLv2" \
    build-date="2016-06-02"

# Default command
CMD ["/bin/bash"]
指令 解释
FROM 基础镜像,当前新镜像是基于哪个镜像
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令
EXPOSE 当前容器对外暴露出的端口
WORKDIR 创建容器后的工作目录(即docker run -it centos后进入的目录)
ENV 构建镜像过程中设置环境变量,后续可以使用如(ENV MYPATH /USER/DATA 后续使用方式为WORKDIR $MYPATH)
ADD 将宿主机目录下的文件拷贝进镜像且尝试自动处理url和解压tar压缩包
COPY 类似ADD,拷贝文件和目录道镜像中。将从构建上下文目录中<源路径>的文件/目录复制道新的一层的镜像内的<目标路径>位置 COPY src dest; COPY ["src","dest"]
VOLUME 容器数据卷,在创建容器时自建容器卷,用于保存和持久化(会对应宿主机上/var/lib/docker/volumes/容器名/_data 文件夹)
CMD 指定一个容器启动时要运行的命令
DockerFile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run 之后的参数替换
ENTRYPOINT 指定一个容器启动时要运行的命令
ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数(不会被替换,会在上次命令后追加)
ONBUILD 触发器:当构建一个被继承的DockerFile时运行命令,父镜像在被子继承后,父镜像的onbuild被触发

6.2 案例

6.2.1 自定义镜像mycentos

docker中的centos是精简版,很多命令都用不了,如vim, ifconfig,

现在我们想要一个可以使用vim及ifconfig命令的自定义centos镜像

DockerFile文件如下:

FROM centos
MAINTAINER aluna<wyywfcan@outlook.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 "success--------ok"
CMD /bin/bash
6.2.2 CMD/ENTRYPOINT命令案例

1、CMD案例

首先我们看到tomcat9.0.56的dockerfile文件

#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM openjdk:8-jdk-bullseye

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME

# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR

# see https://www.apache.org/dist/tomcat/tomcat-9/KEYS
# see also "versions.sh" (https://github.com/docker-library/tomcat/blob/master/versions.sh)
ENV GPG_KEYS 48F8E69F6390C9F25CFEDCD268248959359E722B A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243

ENV TOMCAT_MAJOR 9
ENV TOMCAT_VERSION 9.0.56
ENV TOMCAT_SHA512 b4c2c85891e84f0fbd8fec889ef0890d68a2bfa53eb31d4d39fcf5758aa483694af7ac27533ea4bc3fc3fdae56f2fa9c018d4acf872574c0ec5e37bb443599ce

RUN set -eux; \
	\
	savedAptMark="$(apt-mark showmanual)"; \
	apt-get update; \
	apt-get install -y --no-install-recommends \
		ca-certificates \
		curl \
		dirmngr \
		gnupg \
	; \
	\
	ddist() { \
		local f="$1"; shift; \
		local distFile="$1"; shift; \
		local mvnFile="${1:-}"; \
		local success=; \
		local distUrl=; \
		for distUrl in \
# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
			"https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile" \
# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
			"https://downloads.apache.org/$distFile" \
			"https://www-us.apache.org/dist/$distFile" \
			"https://www.apache.org/dist/$distFile" \
			"https://archive.apache.org/dist/$distFile" \
# if all else fails, let's try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
			${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} \
		; do \
			if curl -fL -o "$f" "$distUrl" && [ -s "$f" ]; then \
				success=1; \
				break; \
			fi; \
		done; \
		[ -n "$success" ]; \
	}; \
	\
	ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; \
	echo "$TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
	ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
	export GNUPGHOME="$(mktemp -d)"; \
	for key in $GPG_KEYS; do \
		gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
	done; \
	gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
	tar -xf tomcat.tar.gz --strip-components=1; \
	rm bin/*.bat; \
	rm tomcat.tar.gz*; \
	command -v gpgconf && gpgconf --kill all || :; \
	rm -rf "$GNUPGHOME"; \
	\
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
	mv webapps webapps.dist; \
	mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
	\
	nativeBuildDir="$(mktemp -d)"; \
	tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
	apt-get install -y --no-install-recommends \
		dpkg-dev \
		gcc \
		libapr1-dev \
		libssl-dev \
		make \
	; \
	( \
		export CATALINA_HOME="$PWD"; \
		cd "$nativeBuildDir/native"; \
		gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
		aprConfig="$(command -v apr-1-config)"; \
		./configure \
			--build="$gnuArch" \
			--libdir="$TOMCAT_NATIVE_LIBDIR" \
			--prefix="$CATALINA_HOME" \
			--with-apr="$aprConfig" \
			--with-java-home="$JAVA_HOME" \
			--with-ssl=yes \
		; \
		nproc="$(nproc)"; \
		make -j "$nproc"; \
		make install; \
	); \
	rm -rf "$nativeBuildDir"; \
	rm bin/tomcat-native.tar.gz; \
	\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
	apt-mark auto '.*' > /dev/null; \
	[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
	find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
		| awk '/=>/ { print $(NF-1) }' \
		| xargs -rt readlink -e \
		| sort -u \
		| xargs -rt dpkg-query --search \
		| cut -d: -f1 \
		| sort -u \
		| tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" \
		| xargs -r apt-mark manual \
	; \
	\
	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
	rm -rf /var/lib/apt/lists/*; \
	\
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
	find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
	\
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
	chmod -R +rX .; \
	chmod 777 logs temp work; \
	\
# smoke test
	catalina.sh version

# verify Tomcat Native is working properly
RUN set -eux; \
	nativeLines="$(catalina.sh configtest 2>&1)"; \
	nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
	nativeLines="$(echo "$nativeLines" | sort -u)"; \
	if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
		echo >&2 "$nativeLines"; \
		exit 1; \
	fi

EXPOSE 8080
CMD ["catalina.sh", "run"]

​ 从tomcat的dockerfile文件中可以看到最后一行是 CMD ["catalina.sh", "run"]这一命令,正是因为这一命令tomcat才能启动。

docker run -it -p 7777:8080 tomcat 此命令可以正常启动tomcat容器,

此时我们将命令更换成 docker run -it ip 7777:8080 tomcat ls -l再次启动,这次控制台输出了tomcat 的dockerfile文件第六行定义的 WORKDIR /usr/local/tomcat文件夹中的文件信息。

docker run -it ip 7777:8080 tomcat ls -l这个命令相当于在tomcat启动后执行了 ls -l操作。此时使用 docker ps命令也会发现tomcat没有成功启动,因为tomcat 的 DockerFile文件中最后一行CMD ["catalina.sh", "run"]被 ls -l命令所替换。

2、ENTRYPOINT案例

制作一个IP信息查询器

CMD版

FROM centos
RUN yum install -y curl
CMD ["curl", "-s", "http://ip.cn"]

build上述dockerfile文件 docker build -f 路径 -t myip .

成功后生成 myip镜像文件

此时执行docker run -it myip 成功后输出 当前容器的ip地址

注意:我想在此功能上添加打印http报文头内容,即实现curl -s -i http://ip.cn,此时使用docker run myip -i命令无法达到上述功能,上述命令其实替换了原来的CMD命令,在下面新加了一行CMD -i

ENTRYPOINT版

FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl", "-s", "http://ip.cn"]

build上述dockerfile文件

再使用docker run myip2 -i 即可查询出http报文头,此时可以理解为更改原有命令为CMD ["curl", "-s", "-i", "http://ip.cn"]

6.2.3 自定义tomcat

1、mkdir -p /aluna/mydockerfile/tomcat9/

2、在上述目录touch c.txt

3、cp apache-tomcat-9.0.8.tar.gz 上述路径(将tomcat和jdk复制入上述路径)

4、vim DockerFile

FROM centos
MAINTAINER aluna<wyywfcan@outlook.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把Java和tomcat添加到容器中
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local/
WORKDIR $MYPATH
#配置Java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh"]
# CMD["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out

5、docker build DockerFile -t tomcat9

6、docker images 查看是否创建成功

7、docker run -d -p 9080:8080 --name myt9 -v /aluna/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.9/webapps/test -v /aluna/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true tomcat9(后台启动指定主机端口9080映射容器端口8080,名字取myt9,建立两个两个容器卷并分配写权限)

8、将服务发布至/aluna/mydockerfile/tomcat9/test目录下

posted @ 2021-12-15 16:19  阿伦啊  阅读(141)  评论(0编辑  收藏  举报