Add a couple of questions on containers

Also, fixed some minor styling issues in random_question.py script.
This commit is contained in:
abregman 2021-10-24 22:00:44 +03:00
parent aa420a7eed
commit 51ecb4ff77
5 changed files with 113 additions and 31 deletions

View File

@ -2,7 +2,7 @@
:information_source:  This repo contains questions and exercises on various technical topics, sometimes related to DevOps and SRE :) :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 :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 * 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) * 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 * 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
</b></details>
<details>
<summary>What are some of the best practices regarding writing Dockerfiles that you are following?</summary><br><b>
* 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
</b></details> </b></details>
<details> <details>
@ -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. Swarm management which means you can create new swarms in Docker Cloud.
</b></details> </b></details>
#### Containers - Security
<details>
<summary>A container can cause a kernel panic and bring down the whole host. What preventive actions can you apply to avoid it?</summary><br><b>
* Install only the necessary packages in the container
* Set volumes and container's filesystem to read only
* DO NOT run containers with `--privilged` flag
</b></details>
#### Containers - Docker in Production #### Containers - Docker in Production
<details> <details>

View File

@ -9,4 +9,18 @@
### Bonus ### 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).<br>
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)

View File

@ -6,18 +6,9 @@
https://github.com/bregman-arie/node-hello-world https://github.com/bregman-arie/node-hello-world
https://github.com/bregman-arie/flask-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) 2. Write a Dockerfile you'll use for building an image of the application (you can use any base image you would like)
3. Build an image using the Dockerfile you've just wrote
``` 4. Verify the image exists
FROM alpine 5. [Optional] Push the image you've just built to a registry
LABEL maintainer="your name/email" 6. Run the application
RUN apk add --update nodejs nodejs-npm 7. Verify the app is running
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]
```

View File

@ -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 <your username>/web_app:latest
# Verify with "docker image ls"
docker image push <your username>/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 <container ID/name>
# In the browser, go to 127.0.0.1:80
```

View File

@ -3,48 +3,51 @@ import optparse
def main(): def main():
""" Reads through README.md for question/answer pairs and adds them to a list to randomly select from and quiz yourself. """Reads through README.md for question/answer pairs and adds them to a
- supports skipping quesitons with no documented answer with the -s flag list to randomly select from and quiz yourself.
Supports skipping quesitons with no documented answer with the -s flag
""" """
parser = optparse.OptionParser() 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() options, args = parser.parse_args()
with open('README.md', 'r') as f: with open('README.md', 'r') as f:
text = f.read() text = f.read()
questions = [] questions = []
while True: while True:
question_start = text.find('<summary>') + 9 question_start = text.find('<summary>') + 9
question_end = text.find('</summary>') question_end = text.find('</summary>')
answer_end = text.find('</b></details>') answer_end = text.find('</b></details>')
if answer_end == -1: if answer_end == -1:
break break
question = text[question_start: question_end].replace('<br>', '').replace('<b>', '') question = text[question_start: question_end].replace('<br>', '').replace('<b>', '')
answer = text[question_end + 17: answer_end] answer = text[question_end + 17: answer_end]
questions.append((question, answer)) questions.append((question, answer))
text = text[answer_end + 1:] text = text[answer_end + 1:]
num_questions = len(questions) num_questions = len(questions)
while True: while True:
try: try:
question, answer = questions[random.randint(0, num_questions)] question, answer = questions[random.randint(0, num_questions)]
if options.skip and not answer.strip(): if options.skip and not answer.strip():
continue continue
if input(f'Q: {question} ...Show answer? "y" for yes: ').lower() == 'y': if input(f'Q: {question} ...Show answer? "y" for yes: ').lower() == 'y':
print('A: ', answer) print('A: ', answer)
except KeyboardInterrupt: except KeyboardInterrupt:
break break
print("\nGoodbye! See you next time.") print("\nGoodbye! See you next time.")
if __name__ == '__main__': if __name__ == '__main__':
main() main()