1 Dec, 2016
Before this guide makes much sense, you'll need to follow the Get Started with Docker guide.
This introduces the docker run
command, and also docker ps
and docker ps -a
.
I also ran the example that it shows in the output when you complete the above step:
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
The -it
flag allows you to stay with the running program in the container.
This gives you a bash prompt in a running Ubuntu container. You can run commands like this one:
root@f76401fcc701:/# du -hs /
du: cannot access '/proc/10/task/10/fd/3': No such file or directory
du: cannot access '/proc/10/task/10/fdinfo/3': No such file or directory
du: cannot access '/proc/10/fd/4': No such file or directory
du: cannot access '/proc/10/fdinfo/4': No such file or directory
123M /
root@f76401fcc701:/# df -h
Filesystem Size Used Avail Use% Mounted on
none 60G 394M 56G 1% /
tmpfs 999M 0 999M 0% /dev
tmpfs 999M 0 999M 0% /sys/fs/cgroup
/dev/vda2 60G 394M 56G 1% /etc/hosts
shm 64M 0 64M 0% /dev/shm
root@f76401fcc701:/# free -m
total used free shared buff/cache available
Mem: 1997 60 1346 156 590 1620
Swap: 3994 0 3994
This demonstrates how to find existing software on docker hub and introduces the docker images
command.
It also demonstrates how you can pass arguments to commands run in the conatiner:
$ docker run docker/whalesay cowsay boo-boo
_________
< boo-boo >
---------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
After this you can follow the Google Custom Runtime quickstart but even if you don't want to deploy the example, you can run it locally.
git clone https://github.com/GoogleCloudPlatform/appengine-custom-runtimes-samples.git
cd appengine-custom-runtimes-samples/nginx
You can now build the container by giving it a name and specifying the current directory with a .
:
docker build -t local-nginx .
Then you can run the image:
docker run local-nginx
And look at running containers:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b07e46ccc1af local-nginx "nginx -g 'daemon off" 21 seconds ago Up 20 seconds 80/tcp, 443/tcp high_goldwasser
You can see that the image uses ports 80 and 443. This is becuase our Dockerfile
specifies FROM nginx
, and the nginx Dockerfile
specifies EXPOSE 80 443
You can see from the nginx.conf
that the server is actually running on
8080 but this is not exposed. We need to map a port on the local machine to a
port in the container.
Stop the container with Ctrl+C and then run it again with the mapping:
docker run -p 8080:8080 local-nginx
This time the port mapping looks like this:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4dae50e0d425 local-nginx "nginx -g 'daemon off" 9 seconds ago Up 8 seconds 80/tcp, 443/tcp, 0.0.0.0:8080->8080/tcp cocky_ride
You can now fetch the page served based on www/index.html
from the running Nginx server:
$ curl http://localhost:8080
<!doctype html>
<!--
Copyright 2015 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>Brought to you by Google App Engine.</p>
</body>
</html>
To get a bit more fancy, you can mount local files into the running docker container so you can change them locally like this:
$ git diff
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
index d2a1ba7..e165994 100644
--- a/nginx/Dockerfile
+++ b/nginx/Dockerfile
@@ -20,5 +20,5 @@ RUN mkdir -p /usr/share/nginx/www/_ah && \
echo "healthy" > /usr/share/nginx/www/_ah/health
# Finally, all static assets.
-ADD www/ /usr/share/nginx/www/
-RUN chmod -R a+r /usr/share/nginx/www
+# ADD www/ /usr/share/nginx/www/
+# RUN chmod -R a+r /usr/share/nginx/www
You'll need to rebuild the image. If you give it the same name the old one will be overwritten:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
local-nginx latest 8c1e7d8edfbb 40 minutes ago 181.5 MB
$ docker build -t local-nginx .
Sending build context to Docker daemon 9.728 kB
Step 1 : FROM nginx
---> abf312888d13
Step 2 : COPY nginx.conf /etc/nginx/nginx.conf
---> Using cache
---> 809f97c0d8b4
Step 3 : RUN mkdir -p /var/log/app_engine
---> Using cache
---> 00253b89a16e
Step 4 : RUN mkdir -p /usr/share/nginx/www/_ah && echo "healthy" > /usr/share/nginx/www/_ah/health
---> Using cache
---> 7fd0613b89da
Successfully built 7fd0613b89da
nd29030:nginx jgardner$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
local-nginx latest 7fd0613b89da 40 minutes ago 181.5 MB
Notice how the IMAGE ID
has changed.
Now you can map a volume too:
$ docker run -p 8080:8080 --volume $PWD/www:/usr/share/nginx/www local-nginx
Tip:
If you put the --volume
flag at the end by mistake you'll get an error like this:
$ docker run -p 8080:8080 local-nginx --volume $PWD/www:/usr/share/nginx/www
docker: Error response from daemon: invalid header field value "oci runtime error: container_linux.go:247: starting container process caused \"exec: \\\"--volume\\\": executable file not found in $PATH\"\n".
If you try to use a relative path such as --volume www:/usr/share/nginx/www
Docker won't complain, but the volume won't be mounted.
To connect to a running instance you can use this trick...
First, work out the container name for the image you are using:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d49ab1018b7f local-nginx "nginx -g 'daemon off" 3 minutes ago Up 3 minutes 80/tcp, 443/tcp, 0.0.0.0:8080->8080/tcp goofy_cori
in this case goofy_cori
, and then run this:
$ docker exec -it goofy_cori /bin/bash
From within the container, you can now explore:
root@d49ab1018b7f:/# ls -l /usr/share/nginx/
total 4
drwxr-xr-x 2 root root 4096 Nov 28 18:12 html
drwxr-xr-x 3 root root 102 Nov 30 12:37 www
Now that the directories are in sync, you can make changes to your local www
directory and they'll be reflected in the container. When you remove images,
you need to also tell docker to stop keeping track of the volume, otherwise
you'll eventually run out of memory.
Google provide Docker images for their custom runtimes so that you can run your code locally in exactly the same environment as remotely.
https://cloud.google.com/appengine/docs/flexible/custom-runtimes/build
https://github.com/GoogleCloudPlatform/nodejs-docker
If you have the Google Cloud SDK and Beta Commands installed, you can create a custom Docker set up like this:
gcloud beta app gen-config --custom
Put your app.js
in place and then run it with:
docker run -p 8080:8080 api
You can visit http://localhost:8080 and see the API running node in the container.
This doesn't handle Ctrl+C very well, so you can stop the container like this:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d63f48ea9b5 api "/bin/sh -c 'npm star" 6 minutes ago Up 6 minutes stupefied_shirley
$ docker stop stupefied_shirley
stupefied_shirley
Once you are happy with the image you can deploy it to Google Cloud like this:
gcloud app deploy
To see your app run in the cloud, enter the following address in your web browser:
https://
Copyright James Gardner 1996-2020 All Rights Reserved. Admin.