Docker1之Container
An image is a lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and config files.
A container is a runtime instance of an image—what the image becomes in memory when actually executed. It runs completely isolated from the host environment by default, only accessing host files and ports if configured to do so.
Containers run apps natively on the host machine’s kernel. They have better performance characteristics than virtual machines that only get virtual access to host resources through a hypervisor. Containers can get native access, each one running in a discrete process, taking no more memory than any other executable.
building an app the Docker way.
We’ll start at the bottom of the hierarchy of such an app, which is a container, which we cover on this page.
Above this level is a service, which defines how containers behave in production, covered in Part 3.
Finally, at the top level is the stack, defining the interactions of all the services, covered in Part 5.
- Stack
- Services
- Container (you are here)
development environment
In the past, if you were to start writing a Python app, your first order of business was to install a Python runtime onto your machine. But, that creates a situation where the environment on your machine has to be just so in order for your app to run as expected; ditto for the server that runs your app.
With Docker, you can just grab a portable Python runtime as an image, no installation necessary. Then, your build can include the base Python image right alongside your app code, ensuring that your app, its dependencies, and the runtime, all travel together.
These portable images are defined by something called a Dockerfile
.
Dockerfile will define what goes on in the environment inside your container.
Access to resources like networking interfaces and disk drives is virtualized inside this environment, which is isolated from the rest of your system, so you have to map ports to the outside world, and be specific about what files you want to “copy in” to that environment. However, after doing that, you can expect that the build of your app defined in this Dockerfile
will behave exactly the same wherever it runs.
# Use an official Python runtime as a parent image
FROM python:2.7-slim # Set the working directory to /app
WORKDIR /app # Copy the current directory contents into the container at /app
ADD . /app # Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt # Make port 80 available to the world outside this container
EXPOSE 80 # Define environment variable
ENV NAME World # Run app.py when the container launches
CMD ["python", "app.py"]
Proxy servers can block connections to your web app once it’s up and running. If you are behind a proxy server, add the following lines to your Dockerfile, using the ENV
command to specify the host and port for your proxy servers:
# Set proxy server, replace host:port with values for your servers
ENV http_proxy host:port
ENV https_proxy host:port
The app itself
Create two more files, requirements.txt
and app.py
, and put them in the same folder with the Dockerfile
. This completes our app, which as you can see is quite simple. When the above Dockerfile
is built into an image, app.py
andrequirements.txt
will be present because of that Dockerfile
’s ADD
command, and the output from app.py
will be accessible over HTTP thanks to the EXPOSE
command.
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket # Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(__name__) @app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
we see that pip install -r requirements.txt
installs the Flask and Redis libraries for Python, and the app prints the environment variable NAME
, as well as the output of a call to socket.gethostname()
. Finally, because Redis isn’t running (as we’ve only installed the Python library, and not Redis itself), we should expect that the attempt to use it here will fail and produce the error message.
Accessing the name of the host when inside a container retrieves the container ID, which is like the process ID for a running executable.
That’s it! You don’t need Python or anything in requirements.txt
on your system, nor will building or running this image install them on your system. It doesn’t seem like you’ve really set up an environment with Python and Flask, but you have.
Build the app
We are ready to build the app. Make sure you are still at the top level of your new directory. Here’s what ls
should show:
$ ls
Dockerfile app.py requirements.txt
Now run the build command. This creates a Docker image, which we’re going to tag using -t
so it has a friendly name
docker build -t friendlyhello .
Where is your built image? It’s in your machine’s local Docker image registry:
$ docker images REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
Run the app
Run the app, mapping your machine’s port 4000 to the container’s published port 80 using -p
:
docker run -p 4000:80 friendlyhello
ou should see a message that Python is serving your app at http://0.0.0.0:80
. But that message is coming from inside the container, which doesn’t know you mapped port 80 of that container to 4000, making the correct URL http://localhost:4000
.
If you are using Docker Toolbox on Windows 7, use the Docker Machine IP instead of localhost
. For example, http://192.168.99.100:4000/. To find the IP address, use the command docker-machine ip
.
You can also use the curl
command in a shell to view the same content.
$ curl http://localhost:4000 <h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
This port remapping of 4000:80
is to demonstrate the difference between what you EXPOSE
within the Dockerfile
, and what you publish
using docker run -p
. In later steps, we’ll just map port 80 on the host to port 80 in the container and use http://localhost
.
Hit CTRL+C
in your terminal to quit.
On Windows, explicitly stop the container
On Windows systems, CTRL+C
does not stop the container. So, first type CTRL+C
to get the prompt back (or open another shell), then typedocker container ls
to list the running containers, followed bydocker container stop <Container NAME or ID>
to stop the container. Otherwise, you’ll get an error response from the daemon when you try to re-run the container in the next step.
run the app in the background, in detached mode:
docker run -d -p 4000:80 friendlyhello
You get the long container ID for your app and then are kicked back to your terminal. Your container is running in the background. You can also see the abbreviated container ID with docker container ls
(and both work interchangeably when running commands):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
You’ll see that CONTAINER ID
matches what’s on http://localhost:4000
.
use docker container stop
to end the process, using the CONTAINER ID
, like so:
docker container stop 1fa4ab2cf395
Share your image
how to push to registries when you want to deploy containers to production.
upload our built image and run it somewhere else.
A registry is a collection of repositories, and a repository is a collection of images—sort of like a GitHub repository, except the code is already built. An account on a registry can create many repositories. The docker
CLI uses Docker’s public registry by default.
We’ll be using Docker’s public registry here just because it’s free and pre-configured, but there are many public ones to choose from, and you can even set up your own private registry using Docker Trusted Registry.
Log in with your Docker ID
If you don’t have a Docker account, sign up for one at cloud.docker.com. Make note of your username.
Log in to the Docker public registry on your local machine.
$ docker login
Tag the image
The notation for associating a local image with a repository on a registry isusername/repository:tag
The tag is optional, but recommended, since it is the mechanism that registries use to give Docker images a version. Give the repository and tag meaningful names for the context,
such as get-started:part2
. This will put the image in the get-started
repository and tag it as part2
.
put it all together to tag the image. Run docker tag image
with your username, repository, and tag names so that the image will upload to your desired destination. The syntax of the command is:
docker tag image username/repository:tag
docker tag friendlyhello john/get-started:part2
Run docker images to see your newly tagged image. (You can also use docker image ls
.)
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
john/get-started part2 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
...
Publish the image
Upload your tagged image to the repository:
docker push username/repository:tag
Once complete, the results of this upload are publicly available. If you log in to Docker Hub, you will see the new image there, with its pull command.
Pull and run the image from the remote repository
use docker run
and run your app on any machine with this command:
If the image isn’t available locally on the machine, Docker will pull it from the repository.
docker run -p 4000:80 username/repository:tag $ docker run -p 4000:80 john/get-started:part2
Unable to find image 'john/get-started:part2' locally
part2: Pulling from john/get-started
10a267c67f42: Already exists
f68a39a6a5e4: Already exists
9beaffc0cf19: Already exists
3c1fe835fb6b: Already exists
4c9f1fa8fcb8: Already exists
ee7d8f576a14: Already exists
fbccdcced46e: Already exists
Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
Status: Downloaded newer image for john/get-started:part2
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
No matter where docker run
executes, it pulls your image, along with Python and all the dependencies from requirements.txt
, and runs your code. It all travels together in a neat little package, and the host machine doesn’t have to install anything but Docker to run it.
docker build -t friendlyname . # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyname # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyname # Same thing, but in detached mode
docker container ls # List all running containers
docker container ls -a # List all containers, even those not running
docker container stop <hash> # Gracefully stop the specified container
docker container kill <hash> # Force shutdown of the specified container
docker container rm <hash> # Remove specified container from this machine
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag <image> for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry
Docker1之Container的更多相关文章
- Centos7的安装、Docker1.12.3的安装,以及Docker Swarm集群的简单实例
目录 [TOC] 1.环境准备 本文中的案例会有四台机器,他们的Host和IP地址如下 c1 -> 10.0.0.31 c2 -> 10.0.0.32 c3 -> 10.0.0. ...
- windows container (docker) 容器资料笔记
背景 业务需求:简化公司私有云,公有云的部署,尝试寻找更好的,更优化的技术方案替换现有的虚拟机部署方案. 技术背景: .net Docker 学习资料 Docker中文社区: http://www.d ...
- [转载] Centos7的安装、Docker1.12.3的安装,以及Docker Swarm集群的简单实例
1.环境准备 本文中的案例会有四台机器,他们的Host和IP地址如下 c1 -> 10.0.0.31 c2 -> 10.0.0.32 c3 -> 10.0.0.33 c4 -&g ...
- (转) Docker - Docker1.12服务发现,负载均衡和Routing Mesh
看到一篇介绍 Docker swarm以及如何编排的好文章,挪放到这里,自己学习的同时也分享出来. 原文链接: http://wwwbuild.net/dockerone/414200.html -- ...
- Ubuntu16.04安装Docker1.12+开发实例+hello world+web应用容器
本次主要是详细记录Docker1.12在Ubuntu16.04上的安装过程,创建Docker组(避免每次敲命令都需要sudo),Docker常用的基本命令的总结,在容器中运行Hello world,以 ...
- 笔记-docker-1
笔记-docker-1 1. 简介 1.1. 什么是Docker? Docker 是世界领先的软件容器平台.开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问 ...
- Docker---(1)Docker 简介
原文:Docker---(1)Docker 简介 版权声明:欢迎转载,请标明出处,如有问题,欢迎指正!谢谢!微信:w1186355422 https://blog.csdn.net/weixin_39 ...
- 在docker中运行ASP.NET Core Web API应用程序(附AWS Windows Server 2016 widt Container实战案例)
环境准备 1.亚马逊EC2 Windows Server 2016 with Container 2.Visual Studio 2015 Enterprise(Profresianal要装Updat ...
- .Container与.container_fluid区别
.Container与.container_fluid是bootstrap中的两种不同类型的外层容器,两者的区别是:.container 类用于固定宽度并支持响应式布局的容器..container-f ...
随机推荐
- CocoaPod 问题(I)
问题一 报错:_OBJC_CLASS_$_ 方案:https://blog.csdn.net/duxinfeng2010/article/details/8265273 问题二: [!] Oh no, ...
- numpy 数据处理
np.meshgrid() meshgrid 传入两个一维数组,返回第一个二维数组用第一个传入的一维数组为行,第二个传入的一维数组为列返回的第二个数组是以第二个传入的一维数组为行,第一个一维数组为列 ...
- mysql+servlet+jsp实现数据库的增删改查
首先,了解数据库目前我们仅仅用来存放数据,在这里我们在数据库中生成一个表,包含id,classname,teacher,location.Tomcat用来配置eclipse,只有这样我们才能使用JSP ...
- PHP框架CI CodeIgniter 的log_message开启日志记录方法
PHP框架CI CodeIgniter 的log_message开启日志记录方法 第一步:index.php文件,修改环境为开发环境define(‘ENVIRONMENT’, ‘development ...
- python内置函数的简单使用和介绍
"""内置函数的简单使用和介绍参考链接:https://docs.python.org/3/library/functions.html ""&quo ...
- python 实现有序字典
python 实现有序字典 Python默认的字典,是不按顺序存储.输出我们添加在字典中的内容的,即是无序的字典.python 使用OrderedDict函数实现有序的字典. 示例: d = dict ...
- [转载]C#中使用正则表达式验证电话号码、手机号、身份证号、数字和邮编
原文出处:https://www.cnblogs.com/wuhuisheng/archive/2011/03/23/1992652.html 验证电话号码的主要代码如下: public bool I ...
- 阿里云centos远程连接mysql
首先在服务器管理控制台设置防火墙规则 添加规则 使用root登录到mysql 添加一个用户名,权限为%的远程连接用户 grant all on *.* to 'yuancheng'@'%' ident ...
- mysql 虚拟列导入报错1906说明
当表中有虚拟列,使用mysqldump导出后,执行source导入的时候,会出现下列错误: 对于mariadb 10.2,该错误忽略即可,不影响导入.对于mysql 5.7,截止5.7.9该错误没有解 ...
- The address where a.out.debug has been loaded is missing以及No symbol "*" in current context原因与解决方法
最近,在debug core的时候,发现p 变量的时候提示“No symbol "*" in current context”,我们的代码使用-g编译的,经查有可能是下列几个原因或 ...