I have deployed this using Kubernetes:
apiVersion: apps/v1
kind: Deployment
metadata:
name: voting-app-deploy
labels:
name: voting-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: voting-app-pod
app: demo-voting-app
template:
metadata:
name: voting-app-pod
labels:
name: voting-app-pod
app: demo-voting-app
spec:
containers:
- name: voting-app
image: kodekloud/examplevotingapp_vote:v1
ports:
- containerPort: 80
With this Service:
apiVersion: v1
kind: Service
metadata:
name: voting-service
labels:
name: voting-service
app: demo-voting-app
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30004
selector:
name: voting-app-pod
app: demo-voting-app
After checking if the Pods are running, I get a shell to the running container where I can see the source code and make changes using vi:
kubectl exec -it podsname -- sh
The problem is whenever I destroy the deployment and bring it back I lose all my changes in the source code.
This is the application's Dockerfile, which I got from within the running container:
# Using official python runtime base image
FROM python:2.7-alpine
# Set the application directory
WORKDIR /app
# Install our requirements.txt
ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
# Copy our code from the current folder to /app inside the container
ADD . /app
# Make port 80 available for links and/or publish
EXPOSE 80
# Define our command to be run when launching the container
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:80", "--log-file", "-", "--access-logfile", "-", "--workers", "4", "--keep-alive", "0"]
So, how can I get this source code and generate a new image?
You should use volumes.
Volumes will allow you to map the src
code folder in the container to a path outside of your container and it will not be destroyed during restart since it will be store outside of your container.
You can see a working sample with explanation here: https://github.com/nirgeier/KubernetesLabs/tree/master/Labs/09-StatefulSet
emptyDir
emptyDir
is the default volume and it's being deleted when the pod is deleted, but I'm using it here to show you a sample on how to use volumes.
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
Quick and dirty
If you change your code often and this isn't a production environment you can use the --reload
that's according to this thread is available since gunicorn 19.0. this option makes the server reload your code changes into new workers.
Then when you want to save your new image you can use docker commit
to "commit" or save your changes to a new image like so:
docker commit running_container_name_or_id imagerepo/image-name:tag
Though this isn't that recommended in the long run just for small fixes and checks.
Long term preferred usage If you want a long term method method either develop locally with a mounted bind-mount (map a folder from the host machine to the docker container) and build a final image for kubernetes, or you could mount your source code using a config map like in this example:
apiVersion: v1
kind: ConfigMap
metadata:
name: file-configmap
namespace: default
data:
config.conf: |
[mysqld]
binlog-format=mixed
Pod (usage in deployment is the same):
apiVersion: v1
kind: Pod
metadata:
name:
spec:
containers:
- name: container-name
image: image-name
volumeMounts:
- name: my-file-volume
mountPath: /path/in/container/config.conf
subPath: config.conf
volumes:
- name: my-file-volume
configMap:
name: file-configmap
In you container(kubectl exec), use ps | grep gunicorn
find the process of your application. Killed it then start it again.
I've found a solution to my problem that's not common, I guess. I have to clarify that i'm not working on production environment. I just want to "steal" the source code from an image, since I don't have access to the repository.
Here is what I did:
1 . Created a folder and subfolder to organize the code. 2. Got a shell inside the pod's container:
docker exec -it containername sh
or
kubectl exec -it podsname -- sh
cp -R /app /dados/
FROM kodekloud/examplevotingapp_vote:v1
RUN rm -rf /app/*.*
COPY ./dados/app /app
docker build -t myusername/my-voting-app .
docker tag kaiohenricunha/my-voting-app kaiohenricunha/my-voting-app
docker push kaiohenricunha/my-voting-app