From 51ecb4ff7785dcea69db8866bcf0adcf021d13c8 Mon Sep 17 00:00:00 2001 From: abregman Date: Sun, 24 Oct 2021 22:00:44 +0300 Subject: [PATCH] Add a couple of questions on containers Also, fixed some minor styling issues in random_question.py script. --- README.md | 22 +++++++- .../devops/ci_for_open_source_project.md | 16 +++++- exercises/devops/containerize_app.md | 19 ++----- .../devops/solutions/containerize_app.md | 54 +++++++++++++++++++ scripts/random_question.py | 33 ++++++------ 5 files changed, 113 insertions(+), 31 deletions(-) create mode 100644 exercises/devops/solutions/containerize_app.md diff --git a/README.md b/README.md index 5bd5e31..6b17a6f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ :information_source:  This repo contains questions and exercises on various technical topics, sometimes related to DevOps and SRE :) -:bar_chart:  There are currently **1825** questions +:bar_chart:  There are currently **1840** questions :books:  To learn more about DevOps and SRE, check the resources in [devops-resources](https://github.com/bregman-arie/devops-resources) repository @@ -6033,6 +6033,16 @@ It specifies the base layer of the image to be used. Every other instruction is * WORKDIR: sets the working directory inside the image filesystems for all the instructions following it * EXPOSE: exposes the specified port (it doesn't adds a new layer, rather documented as image metadata) * ENTRYPOINT: specifies the startup commands to run when a container is started from the image + * ENV: sets an environment variable to the given value + * USER: sets the user (and optionally the user group) to use while running the image + + +
+What are some of the best practices regarding writing Dockerfiles that you are following?
+ + * Include only the packages you are going to use. Nothing else. + * Specify a tag in FROM instruction. Not using a tag means you'll always pull the latest, which changes over time and might result in unexpected result. + * Do not use environment variables to share secrets
@@ -6333,6 +6343,16 @@ you with more options/features compared to Docker Hub. One example is Swarm management which means you can create new swarms in Docker Cloud.
+#### Containers - Security + +
+A container can cause a kernel panic and bring down the whole host. What preventive actions can you apply to avoid it?
+ + * Install only the necessary packages in the container + * Set volumes and container's filesystem to read only + * DO NOT run containers with `--privilged` flag +
+ #### Containers - Docker in Production
diff --git a/exercises/devops/ci_for_open_source_project.md b/exercises/devops/ci_for_open_source_project.md index 2012224..4e71194 100644 --- a/exercises/devops/ci_for_open_source_project.md +++ b/exercises/devops/ci_for_open_source_project.md @@ -9,4 +9,18 @@ ### Bonus -Containerize the app of the project you forked using any containerization technology you would like. +Containerize the app of the project you forked using any container engine you would like (e.g. Docker, Podman).
+Once you successfully ran the application in a container, submit the Dockerfile to the original project (but be prepared that the maintainer might not need/want that). + +### Suggestions for Projects + +The following is a list of projects without CI (at least at the moment): + +Note: I wrote a script to find these (except the first project on the list, of course) based on some parameters in case you wonder why these projects specifically are listed. + +* [This one](https://github.com/bregman-arie/devops-exercises) - We don't have CI! help! :) +* [image retrieval platform](https://github.com/skx6/image_retrieval_platform) +* [FollowSpot](https://github.com/jenbrissman/FollowSpot) +* [Pyrin](https://github.com/mononobi/pyrin) +* [food-detection-yolov5](https://github.com/lannguyen0910/food-detection-yolov5) +* [Lifely](https://github.com/sagnik1511/Lifely) diff --git a/exercises/devops/containerize_app.md b/exercises/devops/containerize_app.md index d8ecd5c..424b1d3 100644 --- a/exercises/devops/containerize_app.md +++ b/exercises/devops/containerize_app.md @@ -6,18 +6,9 @@ https://github.com/bregman-arie/node-hello-world https://github.com/bregman-arie/flask-hello-world ``` - -`git clone https://github.com/bregman-arie/node-hello-world` - 2. Write a Dockerfile you'll use for building an image of the application (you can use any base image you would like) - -``` -FROM alpine -LABEL maintainer="your name/email" -RUN apk add --update nodejs nodejs-npm -COPY . /src -WORKDIR /src -RUN npm install -EXPOSE 8080 -ENTRYPOINT ["node", "./app.js"] -``` +3. Build an image using the Dockerfile you've just wrote +4. Verify the image exists +5. [Optional] Push the image you've just built to a registry +6. Run the application +7. Verify the app is running diff --git a/exercises/devops/solutions/containerize_app.md b/exercises/devops/solutions/containerize_app.md new file mode 100644 index 0000000..784c089 --- /dev/null +++ b/exercises/devops/solutions/containerize_app.md @@ -0,0 +1,54 @@ +## Containerize an Application + +1. Clone an open source project you would like to containerize. A couple of suggestions: + +``` +https://github.com/bregman-arie/node-hello-world +https://github.com/bregman-arie/flask-hello-world +``` + +`git clone https://github.com/bregman-arie/node-hello-world` + +2. Write a Dockerfile you'll use for building an image of the application (you can use any base image you would like) + +``` +FROM alpine +LABEL maintainer="your name/email" +RUN apk add --update nodejs npm +COPY . /src +WORKDIR /src +RUN npm install +EXPOSE 3000 +ENTRYPOINT ["node", "./app.js"] +``` + +3. Build an image using the Dockerfile you've just wrote + +`docker image build -t web_app:latest .` + +4. Verify the image exists + +`docker image ls` + +5. [Optional] Push the image you've just built to a registry + +``` +docker login +docker image tag web_app:latest /web_app:latest +# Verify with "docker image ls" +docker image push /web_app:latest +``` + +6. Run the application + +``` +docker container run -d -p 80:3000 web_app:latest +``` + +7. Verify the app is running + +``` +docker container ls +docker logs +# In the browser, go to 127.0.0.1:80 +``` diff --git a/scripts/random_question.py b/scripts/random_question.py index 691125d..a0e2b7e 100644 --- a/scripts/random_question.py +++ b/scripts/random_question.py @@ -3,48 +3,51 @@ import optparse def main(): - """ Reads through README.md for question/answer pairs and adds them to a list to randomly select from and quiz yourself. - - supports skipping quesitons with no documented answer with the -s flag + """Reads through README.md for question/answer pairs and adds them to a + list to randomly select from and quiz yourself. + Supports skipping quesitons with no documented answer with the -s flag """ parser = optparse.OptionParser() - parser.add_option("-s", "--skip", action="store_true",help="skips questions without an answer.", default=False) + parser.add_option("-s", "--skip", action="store_true", + help="skips questions without an answer.", + default=False) options, args = parser.parse_args() - + with open('README.md', 'r') as f: text = f.read() - + questions = [] - + while True: question_start = text.find('') + 9 question_end = text.find('') answer_end = text.find('
') - + if answer_end == -1: break - + question = text[question_start: question_end].replace('
', '').replace('', '') answer = text[question_end + 17: answer_end] questions.append((question, answer)) text = text[answer_end + 1:] - + num_questions = len(questions) - + while True: try: question, answer = questions[random.randint(0, num_questions)] - + if options.skip and not answer.strip(): continue - + if input(f'Q: {question} ...Show answer? "y" for yes: ').lower() == 'y': print('A: ', answer) - + except KeyboardInterrupt: break - + print("\nGoodbye! See you next time.") - + if __name__ == '__main__': main()