重启docker
systemctl restart docker
run busybox
第一次运行
docker run busybox echo “Hello world”
Unable to find image 'busybox:latest' locally
Trying to pull repository docker.io/library/busybox ...
latest: Pulling from docker.io/library/busybox
fc1a6b909f82: Pull complete
Digest: sha256:f79f7a10302c402c052973e3fa42be0344ae6453245669783a9e16da3d56d5b4
Hello world
第二次运行
Hello world
流程解读
Running echo “Hello world” in a container based on the busybox container image
Js example
app.js
const http = require('http');
const os = require('os');
console.log("Kubia server starting...");
var handler = function(request, response) {
console.log("Received request from " + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
Dockerfile
FROM node:7
ADD app.js /app.js
CMD node app.js
app.js 和 Dockerfile 放入同一个空目录下
build image
docker build -t kubia .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM node:7
Trying to pull repository docker.io/library/node ...
7: Pulling from docker.io/library/node
ad74af05f5a2: Pull complete
2b032b8bbe8b: Pull complete
a9a5b35f6ead: Pull complete
3245b5a1c52c: Pull complete
afa075743392: Pull complete
9fb9f21641cd: Pull complete
3f40ad2666bc: Pull complete
49c0ed396b49: Pull complete
Digest: sha256:af5c2c6ac8bc3fa372ac031ef60c45a285eeba7bce9ee9ed66dad3a01e29ab8d
---> d9aed20b68a4
Step 2 : ADD app.js /app.js
---> 8c5a1ce433c8
Removing intermediate container 49a87be14c2e
Step 3 : CMD node app.js
---> Running in a589b2ba129d
---> 4c82056ab20a
Removing intermediate container a589b2ba129d
Successfully built 4c82056ab20a
The build command tell Docker to build an image called “kubia” based on the contents of the current directory (note the dot(点号) at the end of the build command). Docker will look for the Dockerfile in the directory and build the image based on the instructions in the file.
During the build process, Docker will first pull the base image (node:7) from the public image repository (Docker Hub), unless(除非) the image has already been pulled and is stored on your machine.
Figure: Building a new container image from a Dockerfile
The build process isn’t performed by the Docker client, actually. The contents of the whole directory are uploaded to the Docker daemon and the image is built there. The client and daemon don’t need to be on the same machine at all. If you’re using Docker on a non-Linux OS, the client is on your host OS, but the daemon runs inside a VM. Because all the files in the build directory are uploaded to the daemon, if it contains a lot of large files and the daemon is not running locally, the upload may take quite some time.
TIP: Don’t include any unnecessary files in the build directory, because they will slow down the build process –
especially when the Docker daemon(守护进程) is on another machine.
IMAGE LAYERS
When building an image, a new layer is created for each individual command in the Dockerfile. So, during the build of our image, after pulling all the layers of the base image, Docker will create a new layer on top of them and add the app.js file into it. Then, it will create yet another layer which will specify the command that should be executed when the image is run. This last layer will then be tagged as kubia:latest. This is shown in below figure, which also shows how a different image called other:latest would use the same layers of the NodeJS image as our own image does.
Figure: Container images are composed of layers, which can be shared among different images
Running the container image
docker run --name kubia-container -p 8080:8080 -d kubia
This tells Docker to run a new container called kubia-container from the kubia image. The container will be detached (分离) from the console (-d flag)(后台运行标志), which means it will run in the background(这意味着在后台运行. Port 8080 on the local machine will be mapped to port 8080 inside the container
(-p 8080:8080 option), so we can access the app through http://localhost:8080. (http://10.239.47.144:8080)
access our application at http://localhost:8080 (be sure to replace localhost with the hostname or IP of the Docker host if necessary):
curl localhost:8080
You've hit 9eba5880ebef
There’s the response from our app. Our tiny(微小) little application is now running inside a container, isolated from everything else. As you can see, it is returning 9eba5880ebef as its hostname, and not the actual hostname of our host machine. The hexadecimal(十六进制) number is actually the id of the Docker container.
When the build process completes, we have a new image stored locally. We can see it by telling Docker to list all locally stored images:
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kubia latest 4c82056ab20a About an hour ago 660.3 MB
Let’s list all running containers, so we can examine the list
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9eba5880ebef kubia "/bin/sh -c 'node app" 13 minutes ago Up 13 minutes 0.0.0.0:8080->8080/tcp kubia-container
The docker ps command only shows the most basic information about the containers. To see additional information, we can use docker inspect:
# docker inspect kubia-container
[
{
"Id": "9eba5880ebef932e10699e6ce9636b03c529df338dae78ffefa9850246a84cb6",
"Created": "2019-04-17T08:27:03.21880997Z",
"Path": "/bin/sh",
"Args": [
"-c",
"node app.js"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 89671,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-04-17T08:27:05.06796618Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:4c82056ab20af299484c032c3909311b833625142f4ca00bd148a39f6ad2756b",
Exploring the inside of a running container
The Node.js image we’ve based our image on, contains the bash shell, so we can run the shell inside the container like this:
# docker exec -it kubia-container bash
root@9eba5880ebef:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4332 636 ? Ss 08:27 0:00 /bin/sh -c node app.js
root 7 0.0 0.0 813596 16260 ? Sl 08:27 0:00 node app.js
root 13 1.6 0.0 20220 1904 ? Ss 08:50 0:00 bash
root 19 0.0 0.0 17496 1136 ? R+ 08:50 0:00 ps aux
This will run bash inside the existing kubia-container container. The bash process will have the same Linux namespaces as the main container process. This allows us to explore the container from within and see how Node.js and our app actually see the system when running inside the container. The -it option is shorthand for two options:
- -i, which makes sure STDIN is kept open (we need this to be able to enter commands into the shell), and
- -t, which allocates a pseudo terminal (TTY). We need both if we want the use the shell like we’re used to.
Only four processes. We don’t see any other processes from the host OS.
PROCESSES IN A CONTAINER ACTUALLY RUN IN THE HOST OPERATING SYSTEM
If we now open another terminal and list the processes on the host OS itself, we will, among all other host’s processes, also see the processes running in the container.
# ps aux | grep app.js
root 89671 0.0 0.0 4332 636 ? Ss 16:27 0:00 /bin/sh -c node app.js
root 89700 0.0 0.0 813596 16260 ? Sl 16:27 0:00 node app.js
This proves that processes running in the container are actually running in the host OS. If you have a keen(敏锐) eye, you may have noticed that the processes have different IDs inside the container vs. on the host. This is because the container is using its own PID Linux namespace and has a completely isolated process tree, along with its own numbering(编号) of processes.
THE CONTAINER’S FILESYSTEM IS ALSO ISOLATED
Like having an isolated process tree, each container also has an isolated filesystem. Listing the contents of the root directory inside the container will only show the files in the container and will include all the files that are in the image plus any files that are created while the container is running
root@9eba5880ebef:/# ls -l
total 16
-rw-r--r--. 1 root root 354 Apr 17 07:36 app.js
drwxr-xr-x. 2 root root 4096 Jul 24 2017 bin
drwxr-xr-x. 2 root root 6 Jul 13 2017 boot
drwxr-xr-x. 5 root root 360 Apr 17 08:27 dev
drwxr-xr-x. 56 root root 4096 Apr 17 08:27 etc
drwxr-xr-x. 3 root root 18 Jul 26 2017 home
drwxr-xr-x. 9 root root 123 Jul 24 2017 lib
drwxr-xr-x. 2 root root 34 Jul 23 2017 lib64
drwxr-xr-x. 2 root root 6 Jul 23 2017 media
drwxr-xr-x. 2 root root 6 Jul 23 2017 mnt
drwxr-xr-x. 3 root root 18 Aug 18 2017 opt
dr-xr-xr-x. 709 root root 0 Apr 17 08:27 proc
drwx------. 3 root root 51 Aug 18 2017 root
drwxr-xr-x. 4 root root 45 Apr 17 08:27 run
drwxr-xr-x. 2 root root 4096 Jul 23 2017 sbin
drwxr-xr-x. 2 root root 6 Jul 23 2017 srv
dr-xr-xr-x. 13 root root 0 Jan 21 01:30 sys
drwxrwxrwt. 2 root root 6 Jul 24 2017 tmp
drwxr-xr-x. 10 root root 105 Aug 18 2017 usr
drwxr-xr-x. 11 root root 139 Jul 26 2017 var
To exit the container, we simply exit the shell with the exit command and we’ll return to our host machine, just logging out of an ssh session, for example.
An application will not only see its own unique filesystem, but also processes, users, hostname and network interfaces.(拥有独立的)
Stopping and removing a container
The -a option prints out all the containers, those running and those that have been stopped. To truly remove a container, we need to remove it with the docker rm command:
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9eba5880ebef kubia "/bin/sh -c 'node app" About an hour ago Up About an hour 0.0.0.0:8080->8080/tcp kubia-container
89cf98f5544d busybox "echo “Hello world\xe2" About an hour ago Exited (0) About an hour ago backstabbing_lichterman
3a3bd67e8256 busybox "echo 'Hello world'" 2 hours ago Exited (0) 2 hours ago determined_kirch
fa0290d927ce busybox "echo 'Hello world'" 2 hours ago Exited (0) 2 hours ago evil_khorana
To stop our app, we simply tell Docker to stop the kubia-container container:
# docker stop kubia-container
kubia-container
Then
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9eba5880ebef kubia "/bin/sh -c 'node app" About an hour ago Exited (137) 26 seconds ago kubia-container
89cf98f5544d busybox "echo “Hello world\xe2" About an hour ago Exited (0) About an hour ago backstabbing_lichterman
3a3bd67e8256 busybox "echo 'Hello world'" 3 hours ago Exited (0) 3 hours ago determined_kirch
fa0290d927ce busybox "echo 'Hello world'" 3 hours ago Exited (0) 3 hours ago evil_khorana
bc01b1ff46d9 centos7:beaver "/usr/sbin/init" 23 months ago Exited (1) 3 hours ago 0.0.0.0:50003->22/tcp slave1
453d7ffd8b1e centos7:beaver "/usr/sbin/init" 23 months ago Exited (1) 3 hours ago 0.0.0.0:50002->22/tcp master
Also can start
[root@bdpe822n1 ~]# docker start kubia-container
kubia-container
To truly remove a container, we need to remove it with the docker rm command:
docker rm kubia-container
This deletes the container. All its contents are removed and it can’t be started again.
Pushing the image to an image registry
To allow us to run the image on any other machine, we need to push the image to an external image registry. For the sake of simplicity(为简单起见), we won’t be setting up a private image registry and will instead just push our image to Docker Hub (http://hub.docker.com), which is one of the publicly available registries.
Other widely used such registries are Quay.io and the Google Container Registry.
Before we do that, we need to re-tag our image according Docker Hub’s rules. Docker Hub will allow us to push an image if the image’s repository name starts with our Docker Hub ID. You create your Docker Hub ID by registering at http://hub.docker.com.
TAGGING AN IMAGE UNDER AN ADDITIONAL TAG
Once we know our ID, we’re ready to rename our image, currently tagged simply as kubia, to zhixingheyitian/kubia
docker tag kubia zhixingheyitian/kubia
出现了两个,但是指向一个image id
This doesn’t rename the tag, it simply creates an additional tag for the same image. Let’s confirm this by listing the images stored on our system with the docker images command:
#docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kubia latest 4c82056ab20a 4 hours ago 660.3 MB
zhixingheyitian/kubia latest 4c82056ab20a 4 hours ago 660.3 MB
PUSHING THE IMAGE TO DOCKER HUB
Before you can actually push the image to Docker Hub, you need to log in under your user ID with the docker login command.
If you don’t log,
# docker push zhixingheyitian/kubia
The push refers to a repository [docker.io/zhixingheyitian/kubia]
ce967b9b826e: Preparing
ab90d83fa34a: Preparing
8ee318e54723: Preparing
e6695624484e: Preparing
5616a6292c16: Waiting
f3ed6cb59ab0: Waiting
654f45ecb7e3: Waiting
2c40c66f7667: Waiting
unauthorized: authentication required
Once you’re logged in,
# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: zhixingheyitian
Password:
Login Succeeded
you can finally push the yourid/kubia image to Docker Hub like this:
# docker push zhixingheyitian/kubia
The push refers to a repository [docker.io/zhixingheyitian/kubia]
ce967b9b826e: Layer already exists
ab90d83fa34a: Layer already exists
8ee318e54723: Layer already exists
e6695624484e: Layer already exists
da59b99bbd3b: Layer already exists
5616a6292c16: Layer already exists
f3ed6cb59ab0: Layer already exists
654f45ecb7e3: Layer already exists
2c40c66f7667: Pushed
latest: digest: sha256:108ae1932e7093ed73a6a36303a8fde8bbfef776b40406343e92b8596910a375 size: 2213
RUNNING THE IMAGE ON A DIFFERENT MACHINE
After the push to Docker Hub is complete, the image will be available to everyone.
在另外的节点上无需登陆,即可pull 和 run
# docker run -p 8080:8080 -d zhixingheyitian/kubia
Unable to find image 'zhixingheyitian/kubia:latest' locally
latest: Pulling from zhixingheyitian/kubia
ad74af05f5a2: Pull complete
2b032b8bbe8b: Pull complete
a9a5b35f6ead: Pull complete
3245b5a1c52c: Pull complete
afa075743392: Pull complete
9fb9f21641cd: Pull complete
3f40ad2666bc: Pull complete
49c0ed396b49: Pull complete
e8185acbed35: Pull complete
Digest: sha256:108ae1932e7093ed73a6a36303a8fde8bbfef776b40406343e92b8596910a375
Status: Downloaded newer image for zhixingheyitian/kubia:latest
3325e8018905ac4b3bd22605e0bfb3507d4e49f523f63610f93a6d02e6f1bc09