Can't figure out how I have to build my Docker architecture - docker

So currently I'm building an API in PHP as different (micro) services which runs on nginx.
I've followed all the Docker fundamental video's and went through the docs, but I still can't figure out how to implement it.
Do I need a server where I push my code to and deploy on the containers (with CI or so)?
Does the container volume get pushed to the hub as well? So my code will be in the container itself?

I think you messed up a bit what's container and what's an image. For me image is something you build on disk to run. And container is an image running on the computer and serving/doing things.
Do I need a server where I push my code to and deploy on the containers
No, you don't. You start building image from some base image, and from a Dockerfile. So make some work dir, copy Dockerfile here, copy your PHP sources here as PHPAPI and in Dockerfile have commands to copy PHP into docker. Along the lines
FROM ubuntu:15.04
MAINTAINER guidsen
RUN apt-get update && \
apt-get install -y nginx && \
apt-get install -y php && \
apt-get autoremove; apt-get clean; apt-get autoclean
RUN mkdir -p /root/PHPAPI
COPY PHPAPI /root/PHPAPI
WORKDIR /root/PHPAPI
CMD /root/PHPAPI/main.php
Does the container volume get pushed to the hub as well? So my code will be in the container itself?
That depends on what do you use to run containers from image. AWS I think require image pulled from Docker hub, so you have to push it here first. Some other cloud providers or private clouds require to push image directly to them. And yes, your code would be in the image and will be run in the container.

Related

Docker - Extending a container with another image?

At my company, we have hardened containers created by the security team, and I would like to extend the hardened container with another docker image. For example, if we have a hardened Debian container, and I want to add Apache, how do I do this?
I understand I can use FROM to use a base, but the examples I've seen, don't add another level of published images to an existing base, but specific commands. Do I just go to the official Dockerhub Apache (HTTP) image and just copy and paste the commands from the github repo? I'm assuming there's a cleaner way (but not sure if there is).
For example, do I
FROM mycompanyprivaterepo/Debian:latest
//some command?
FROM httpd
docker build -t mynewimagewithapache
UPDATE:
After attempting via apt-get apache2 per some comments, it kept hanging on interactive questions, Solved with the help of comments using:
My Dockerfile:
FROM myprivaterepo/hardened-ubuntu
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get -qq install apache2
and building via:
$ docker build -t hardened-ubuntu-apache
Well, as far as I understood, you cannot use multi-stage builds and just
COPY --from=base-image /path/to/file/you-are-interested-in /path/inside/new-stage-image
in order to copy the required data to your preferred image. If this is the case, then you have to create your own Dockerfile with base image as your company mycompanyprivaterepo/Debian:latest, and then just create some layers on top of it in order to install required software, using RUN.

How to make an image from a Docker container

I'm following a tutorial to wrap a tool in a docker container.
In the linked tutorial page, step 2 describes how to create the container
$ docker run -ti ubuntu
and
root#70235f7726cf:/#
I install a number of libraries/programs
$ apt-get install wget build-essential zlib1g-dev libncurses5-dev
[...]
then
exit
Step 3 describes how the docker container is saved into an image but there is only the procedure to save it in a private repo and not in docker hub.
I did some research and the following is the command to push an image to a Docker repository in the Hub
$ docker push myusr/my-repo:mytoolv1
but since I did not save the image the push does not work.
The tutorial I'm following is missing some steps in between or maybe it is me that is missing some knowledge of Docker.
I think you might have some terms mixed up. You can't push containers to dockerhub, you can only push images.
To create a custom image you need a Dockerfile. Something like this:
FROM ubuntu:18.04
RUN apt update
RUN apt install -y wget build-essential zlib1g-dev libncurses5-dev
...
Then from the same folder build the custom image by running
docker build -t myusr/my-repo:mytoolv1 .
Ath thus point you can push the image to dockerhub using the command you tried:
docker push myusr/my-repo:mytoolv1
What is in your mind and is not correct, is that you think you can push container to your local repo, but in fact you are pushing the image.
I hope you know the difference between an image and a container, if not you can search about.
You can create a file called Dockerfile (with no extension and with this exact name) with the following contents:
FROM ubuntu:20.04
# to set time zone as you may encounter some unexpected stuck when selecting time zone during the build
ENV TZ=Asia/Tehran # search more about it in https://www.php.net/manual/en/timezones.php
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update && apt-get install -y wget build-essential zlib1g-dev libncurses5-dev
Now you should build your image:
docker build -t yourrepo/NAME:TAG_VERSION .
example:
docker build -t yourrepo/my_image:1.0.0 .
Now you can push it:
docker push yourrepo/my_image:1.0.0

Create a new version of a container and submit do docker hub

I have a container and I want to make a change to it.
It is hosted at docker hub, and I would like to change one of its commands to install an additional app.
I can see the individual steps in docker hub, but not the dockerfile itself (not sure why).
This is the command I want to change:
/bin/sh -c apk --update add --no-cache openssh bash zip && ....
I want to pull the container, change that line to include an additional package in the add command of apk.
I have been reading about the docker commit --change command but I am unsure how to exactly pinpoint the command I want to change. Do I reference it numerically, saying I want to change line #3?
I will then tag a new version and push, which I know how to do, but I am finding it hard to understand how to change this without docker run -it [name] bash and then push this, as I already did that and it appended a new command after the CMD command, and broke the container...
What hosted on docker hub is actually the image of the container.
This image is hosted in layers. each docker file command represents a new layer. You can't actually change a single layer, You can however create a new docker file based on that image and add new layers.
FROM SOME_BASE_IMAGE
RUN apt-get update && \
apt-get install -y SOME_PACKAGE
(assuming the image has apt package manager)
You'll then have to build the new image with docker build -t IMAGE_REPO:IMAGE_TAG ...
If you don't have access to the Dockerfile, you can't change anything in that container, you can only append more stuff (layers).
This means that, you can't change /bin/sh -c apk --update add --no-cache openssh bash zip && .... for something else, but if your intention is to install / remove more packages, you can do the following:
FROM the_container_you_want_to_change
RUN ...

I found an image on docker hub that I like but doesn't meet my needs. How do I update it and make it my own?

I found an image on docker (https://hub.docker.com/r/realbazso/horizon) that I like. I am trying to update this to where it runs the most current version of this software.
I tested running the image with the arguments provided and it works great, but the version of the VMWare Horizon client that the image has does not have an updated SSL library and cannot connect to the servers I need it to without throwing an SSL error.
I'm super new to docker, but I was wondering if anyone could help me with this. I'm wanting to install it on the ubuntu:14.04 image, but I'm just not able to wrap my head around it.
I am going to add some more information to #user2915097's answer.
The first thing to do when you want to edit/update an already existing image is to see if you can find its Dockerfile. Fortunately, this repo has a Dockerfile attached to it so it makes it easier. I commented the file so that you can understand better what is going on:
# Pulls the ubuntu image. This will serve as the base image for the container. You could change this and use ubuntu:16.04 to get the latest LTS.
FROM ubuntu:14.04
# RUN will execute the commands for you when you build the image from this Dockerfile. This is probably where you will want to change the source
RUN echo "deb http://archive.canonical.com/ubuntu/ trusty partner" >> /etc/apt/sources.list && \
dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -y vmware-view-client
# CMD will execute the command (there can only be one!) when you start/run the container
CMD /usr/bin/vmware-view
A good resource to understand those commands is https://docs.docker.com/engine/reference/builder/. Make sure to visit that page to learn more about Dockerfile!
Once you have a Dockerfile ready to build, navigate to the folder where your Dockerfile is and run:
# Make sure to change the argument of -t
docker build -t yourDockerHubUsername/containerName .
You might need to modify your Dockerfile a few times before it works correctly. If you are having issues with Docker using cached data
as you have the recipe, if you look at
https://hub.docker.com/r/realbazso/horizon/~/dockerfile/
you should create a directory, put this Dockerfile in, modify it, build another image
docker build -t tucker/myhorizon .
launch it, test it, modify again the Dockerfile maybe.
Check the doc R0MANARMY listed

How do I dockerize an existing application...the basics

I am using windows and have boot2docker installed. I've downloaded images from docker hub and run basic commands. BUT
How do I take an existing application sitting on my local machine (lets just say it has one file index.php, for simplicity). How do I take that and put it into a docker image and run it?
Imagine you have the following existing python2 application "hello.py" with the following content:
print "hello"
You have to do the following things to dockerize this application:
Create a folder where you'd like to store your Dockerfile in.
Create a file named "Dockerfile"
The Dockerfile consists of several parts which you have to define as described below:
Like a VM, an image has an operating system. In this example, I use ubuntu 16.04. Thus, the first part of the Dockerfile is:
FROM ubuntu:16.04
Imagine you have a fresh Ubuntu - VM, now you have to install some things to get your application working, right? This is done by the next part of the Dockerfile:
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y python
For Docker, you have to create a working directory now in the image. The commands that you want to execute later on to start your application will search for files (like in our case the python file) in this directory. Thus, the next part of the Dockerfile creates a directory and defines this as the working directory:
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
As a next step, you copy the content of the folder where the Dockerfile is stored in to the image. In our example, the hello.py file is copied to the directory we created in the step above.
COPY . /usr/src/app
Finally, the following line executes the command "python hello.py" in your image:
CMD [ "python", "hello.py" ]
The complete Dockerfile looks like this:
FROM ubuntu:16.04
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y python
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
CMD [ "python", "hello.py" ]
Save the file and build the image by typing in the terminal:
$ docker build -t hello .
This will take some time. Afterwards, check if the image "hello" how we called it in the last line has been built successfully:
$ docker images
Run the image:
docker run hello
The output shout be "hello" in the terminal.
This is a first start. When you use Docker for web applications, you have to configure ports etc.
Your index.php is not really an application. The application is your Apache or nginx or even PHP's own server.
Because Docker uses features not available in the Windows core, you are running it inside an actual virtual machine. The only purpose for that would be training or preparing images for your real server environment.
There are two main concepts you need to understand for Docker: Images and Containers.
An image is a template composed of layers. Each layer contains only the differences between the previous layer and some offline system information. Each layer is fact an image. You should always make your image from an existing base, using the FROM directive in the Dockerfile (Reference docs at time of edit. Jan Vladimir Mostert's link is now a 404).
A container is an instance of an image, that has run or is currently running. When creating a container (a.k.a. running an image), you can map an internal directory from it to the outside. If there are files in both locations, the external directory override the one inside the image, but those files are not lost. To recover them you can commit a container to an image (preferably after stopping it), then launch a new container from the new image, without mapping that directory.
You'll need to build a docker image first, using a dockerFile, you'd probably setup apache on it, tell the dockerFile to copy your index.php file into your apache and expose a port.
See http://docs.docker.com/reference/builder/
See my other question for an example of a docker file:
Switching users inside Docker image to a non-root user (this is for copying over a .war file into tomcat, similar to copying a .php file into apache)
First off, you need to choose a platform to run your application (for instance, Ubuntu). Then install all the system tools/libraries necessary to run your application. This can be achieved by Dockerfile. Then, push Dockerfile and app to git or Bitbucket. Later, you can auto-build in the docker hub from github or Bitbucket. The later part of this tutorial here has more on that. If you know the basics just fast forward it to 50:00.

Resources