preface

Just know nuggets article still has word limit, can divide development.

I used Vue family bucket to develop my personal blog and deployed it on Ali cloud server. Recently, I learned React, so I developed and reconstructed my blog with React.

  • The old vue_blog:vue.cl8023.com

  • The new react_blog:cl8023.com

The main technology stack is as follows:

  • The front page: Next. Js builds the server side rendering page, which is conducive to SEO
  • Background management interface: create-react-app quick setup
  • Service interface: egg.js + Mysql
  • Deployment: Linux + Docker

React Hooks+ egg.js React Hooks+ egg.js React Hooks+ egg.js

The deployment part will be mainly explained here, because it is the first time to contact Docker. I only record my learning experience here, and please give me more advice if there is something wrong.

In this project, the foreground page is node running, the background interface is static HTML, and the service interface needs to be connected to Mysql. I think the deployment of Docker is also a comprehensive example, which can be used as a reference for the later students. The content is rather wordy, and I hope it can help the later students to make less mistakes. Because some are their own understanding, there may be mistakes, but also please correct, learn from each other.

The project address

Source code address: github.com/Moon-Future…

Clone down to the directory oh ~

A, the React

The blog foreground is built with the Next. Js server rendering framework, the background management interface is built with the create-React-app scaffolding, and the service interface is built with the Egg framework (based on Koa). There is nothing to be said about React management and service interfaces. Here are some of the React basics and some of the problems encountered in Next.

Project Contents:

Blog: Foreground interface, next.js

Admin: Create-react-app scaffolding is set up on the background management interface

Service: front and back service interfaces

1. Obtain render data

GetStaticProps and getServerSideProps are the two official apis for rendering the page on the server side, so the initial data is retrieved on the server side and returned to the front-end. (For Next. Js versions 9.3 and older, use getStaticProps or getServerSideProps instead of getInitialProps.)

GetStaticProps: The server gets static data, generates a static HTML page when it gets the data, and then reuses that page on every request

const Article = (props) = > {

    return()}/* Export default class Article extends React.Component {render() {return}} */

export async function getStaticProps(context) {
    try {
        const result = await axios.post(api.getArticleList)
        return {
            props: { articleList: result.data }, // will be passed to the page component as props}}catch (e) {
        return {
            props: { articleList: []},// will be passed to the page component as props}}}export default Article
Copy the code

GetServerSideProps: On each request, the server reobtains the generated HTML page

const Article = (props) = > {

    return()}/* Export default class Article extends React.Component {render() {return}} */

export async function getServerSideProps(context) {
    try {
        const result = await axios.post(api.getArticleList)
        return {
            props: { articleList: result.data }, // will be passed to the page component as props}}catch (e) {
        return {
            props: { articleList: []},// will be passed to the page component as props}}}export default Article
Copy the code

You can see that they are used the same way.

In development mode, NPM run dev is the same as NPM run Dev, and the page is refetched every time it is requested.

In production, NPM run build is used to generate the static HTML page. To get the data from getStaticProps, run start is used to generate the static HTML page. Using getServerSideProps reobtains the data on each request.

The returned data is in the form of objects, and only objects. The key is props, which is passed to the props in the class or function.

Blog: getServerSideProps is used to get a list of blog posts, and the data can change at any time.

In this case, try and catch are used to catch exceptions to prevent data acquisition failure or back-end interface error, and server rendering error cannot return the page.

2. Request after the page is loaded

There is also some data that we don’t want to get rendered to the page on the server, but we want the page to load.

React Hook: useEffect

const Article = (props) = > {

    useEffect(async() = > {await axios.get(' ')}, [])return()}export async function getServerSideProps(context) {
    try {
        const result = await axios.post(api.getArticleList)
        return {
            props: { articleList: result.data }, // will be passed to the page component as props}}catch (e) {
        return {
            props: { articleList: []},// will be passed to the page component as props}}}export default Article
Copy the code

Note here that useEffect, the second parameter, represents whether or not a dependency is executed.

  • No second argument: useEffect the first argument function is executed every time return re-renders the page
  • Parameter [], as shown in the preceding example, indicates that the command is executed only once, independent of any variable
  • Pass [value], an array, which can depend on multiple variables: represents the dependency on the value variable (the value in state). UseEffect is executed only when the value changes

With Class, you can operate in componenDidMount:

export default class Article extends React.Component {

    componenDidMount() {
        await axios.get(' ')}render() {
        return}}export async function getServerSideProps(context) {
    try {
        const result = await axios.post(api.getArticleList)
        return {
            props: { articleList: result.data }, // will be passed to the page component as props}}catch (e) {
        return {
            props: { articleList: []},// will be passed to the page component as props}}}export default Article
Copy the code

3. Page animation

Page to enter and exit the animation to find a more useful libraries framer – motion, www.framer.com/api/motion/

Pages /_app.js will be updated to include Framer-motion

npm install framer-motion -S
Copy the code
import { AnimatePresence } from 'framer-motion'

export default function MyApp({ Component, pageProps, router }) {
  return (
    <AnimatePresence exitBeforeEnter>
      <Component {. pageProps} route={router.route} key={router.route} />
    </AnimatePresence>)}Copy the code

Animate each page by placing motion in front of the element tag, such as pages/article.js

const postVariants = {
  initial: { scale: 0.96.y: 30.opacity: 0 },
  enter: { scale: 1.y: 0.opacity: 1.transition: { duration: 0.5.ease: [0.48.0.15.0.25.0.96]}},exit: {
    scale: 0.6.y: 100.opacity: 0.transition: { duration: 0.5.ease: [0.48.0.15.0.25.0.96]}}},const sentenceVariants = {
  initial: { scale: 0.96.opacity: 1 },
  exit: {
    scale: 0.6.y: 100.x: -300.opacity: 0.transition: { duration: 0.5.ease: [0.48.0.15.0.25.0.96]}}},const Article = (props) = > {
  const { articleList, route } = props
  const [poetry, setPoetry] = useState(null)

  const getPoetry = (data) = > {
    setPoetry(data)
  }

  return (
    <div className="container article-container">
      <Head>
        <title>There is no end to learning</title>
      </Head>

      <Header route={route} />

      <div className="page-background"></div>
      <div style={{ height: '500px' }}></div>

      <Row className="comm-main comm-main-index" type="flex" justify="center">
        <Col className="comm-left" xs={0} sm={0} md={0} lg={5} xl={4} xxl={3}>
          <Author />
          <Project />
          <Poetry poetry={poetry} />
        </Col>

        <Col className="comm-center" xs={24} sm={24} md={24} lg={16} xl={16} xxl={16}>
          <motion.div className="sentence-wrap" initial="initial" animate="enter" exit="exit" variants={sentenceVariants}>
            <PoetrySentence staticFlag={true} handlePoetry={getPoetry} />
          </motion.div>
          <div className="comm-center-bg"></div>
          <motion.div initial="initial" animate="enter" exit="exit" variants={postVariants} className="comm-center-content">
            <BlogList articleList={articleList} />
          </motion.div>
        </Col>
      </Row>
    </div>)}Copy the code

“Motion” will be added to the tag of the element that you want to animate and will pass in parameters like Initial, Animate, exit and variants

const postVariants = {
  initial: { scale: 0.96.y: 30.opacity: 0 },
  enter: { scale: 1.y: 0.opacity: 1.transition: { duration: 0.5.ease: [0.48.0.15.0.25.0.96]}},exit: {
    scale: 0.6.y: 100.opacity: 0.transition: { duration: 0.5.ease: [0.48.0.15.0.25.0.96]}}},// initial Indicates the initial state
// Enter to enter the animation
// exit Indicates the exit status
// Do not want an exit animation, do not write exit variable
Copy the code

< span style = “color: RGB (0, 0, 0); font-size: 14px! Important; line-height: 20px! Important;”

const Article = (props) = >{
    return (
    	<motion.div initial="initial" animate="enter" exit="exit">.</motion.div>)}Copy the code

4. Switch status

Use import Link from ‘Next/Link’ in next.js to switch pages without refreshing them

import Link from 'next/link'

const BlogList = (props) = > {
  return (
    <>
      <Link href={'/detailed?id=' + item.id}> 
        
{item.title}
)}export default BlogList Copy the code

Because it is rendered on the server side, when the Link is clicked, the page does not react for a while. By default, Next. Js has a rotating black triangle in the lower right corner, but it does not attract the user’s attention.

The plugin nProgress is used to load the progress bar from the top

npm install nprogress -S
Copy the code

Change _app.js again

import 'antd/dist/antd.css'
import '.. /static/style/common.less'
import { AnimatePresence } from 'framer-motion'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import Router from 'next/router'

NProgress.configure({
  minimum: 0.3.easing: 'ease'.speed: 800.showSpinner: false,
})
Router.events.on('routeChangeStart'.() = > NProgress.start())
Router.events.on('routeChangeComplete'.() = > NProgress.done())
Router.events.on('routeChangeError'.() = > NProgress.done())

export default function MyApp({ Component, pageProps, router }) {
  return (
    <AnimatePresence exitBeforeEnter>
      <Component {. pageProps} route={router.route} key={router.route} />
    </AnimatePresence>)}Copy the code

The next/ Router is used to monitor the route switching status. You can also customize the loading status.

5. The CSS fails to be loaded

In the Next. Js development mode, when entering a page for the first time, it is found that the current page style fails to load, and must be refreshed to load successfully.

next-css: Routing to another page doesn’t load CSS in development mode

Cant change page with ‘next/link’ & ‘next-css’

Github also found related problems, said to _app.js, but I tried, still not work, but fortunately this situation is only in the development mode, production mode is not a problem, so it is not troubled, so refresh it.

6. Implement setInterval in React Hoos

In the components/PoetrySentence js achieve the effect of dynamic to write a poem, in the class can be used with through setInterval simple implementation, In React Hoot, useEffect is executed every time render is re-rendered, or useEffect is executed only once again depending on [], which is implemented by relying on a single variable plus setTimeout.

The components/PoetrySentence. Js

import { useState, useEffect } from 'react'
import { RedoOutlined } from '@ant-design/icons'
import { getPoetry, formatTime } from '.. /util/index'

const PoetrySentence = (props) = > {
  const [sentence, setSentence] = useState(' ')
  const [finished, setFinished] = useState(false)
  const [words, setWords] = useState(null)
  const { staticFlag, handlePoetry } = props // Whether static display

  useEffect(
    async() = > {if (words) {
        if (words.length) {
          setTimeout(() = > {
            setWords(words)
            setSentence(sentence + words.shift())
          }, 150)}else {
          setFinished(true)}}else {
        let tmp = await todayPoetry()
        if (staticFlag) {
          setFinished(true)
          setSentence(tmp.join(' '))}else {
          setWords(tmp)
          setSentence(tmp.shift())
        }
      }
    },
    [sentence]
  )

  const todayPoetry = () = > {
    return new Promise((resolve) = > {
      const now = formatTime(Date.now(), 'yyyy-MM-dd')
      let poetry = localStorage.getItem('poetry')
      if (poetry) {
        poetry = JSON.parse(poetry)
        if (poetry.time === now) {
          handlePoetry && handlePoetry(poetry)
          resolve(poetry.sentence.split(' '))
          return
        }
      }
      getPoetry.load((result) = > {
        poetry = {
          time: now,
          sentence: result.data.content,
          origin: {
            title: result.data.origin.title,
            author: result.data.origin.author,
            dynasty: result.data.origin.dynasty,
            content: result.data.origin.content,
          },
        }
        handlePoetry && handlePoetry(poetry)
        localStorage.setItem('poetry'.JSON.stringify(poetry))
        resolve(poetry.sentence.split(' '))})})}const refresh = () = > {
    getPoetry.load((result) = > {
      const poetry = {
        time: formatTime(Date.now(), 'yyyy-MM-dd'),
        sentence: result.data.content,
        origin: {
          title: result.data.origin.title,
          author: result.data.origin.author,
          dynasty: result.data.origin.dynasty,
          content: result.data.origin.content,
        },
      }
      handlePoetry && handlePoetry(poetry)
      localStorage.setItem('poetry'.JSON.stringify(poetry))
      if (staticFlag) {
        setSentence(poetry.sentence)
      } else {
        setFinished(false)
        setWords(null)
        setSentence(' ')}}}return (
    <p className="poetry-sentence">
      {sentence}
      {finished ? <RedoOutlined style={{ fontSize: '14px'}}onClick={()= > refresh()} /> : null}
      <span style={{ visibility: finished ? 'hidden' :"'}} >|</span>
    </p>)}export default PoetrySentence
Copy the code

UseEffect depends on the variable sentence, and then changes sentence in useEffect. After sentence is updated, it triggers re-rendering, and then re-executes useEffect. The setInterval effect is perfectly implemented.

7. node-sass

Sass was used in the original project, but in the later deployment and installation of docker dependencies, it was too slow and various errors were reported, which was also frequently encountered before, so it was simply changed to less, with similar syntax and much easier installation.

Second, the Docker

1. What is Docker

Docker is an open source application container engine that allows developers to package their applications and dependencies into a lightweight, portable container that can then be distributed to any popular Linux machine, as well as virtualization.

Containers are completely sandboxed, have no interfaces with each other (like iPhone apps), and most importantly, have very low performance overhead.

2. Why Docker

For me, because I am using Ali cloud server now, I have deployed several projects. If the server expires and the server is replaced, I will need to migrate all projects to the new server, and each project will have to install dependencies, run, nginx configuration and so on in sequence, which is a big headache to think about. With Docker, individual projects and their dependencies are packaged into images that can be produced in any Linux container, making migration and deployment much easier.

In addition, Docker can make the development environment, test environment and production environment consistent, and each container is a service, and it is convenient for the back-end to implement the microservice architecture.

3. The installation

The best way to install Docker is to refer to the official documentation to avoid version updates. Docs.docker.com/engine/inst… English laboured, these two recommend a magic dictionary Continental Dictionary, where will not point where, who use who say good.

Mac and Windows both have clients that can be easily downloaded and installed. In addition, Windows should be distinguished from professional, Enterprise, Education and Home editions

Windows Pro, Enterprise, and Education

Windows home edition

Because I use aliyun Centos 7 server here, so a brief introduction to the Centos installation.

Centos install Docker

First of all, if you have already installed Docker and want to install the latest version, please help the old version first

$sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
Copy the code

There are three installation methods:

  1. Install using the repository
  2. Install from a package
  3. Install using the convenience script

Choose the official recommended first way to Install using the Repository.

1, SET UP THE REPOSITORY

Install the yum-utils toolkit and set up the repository

$ sudo yum install -y yum-utils
$sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Copy the code

2. Install Docker

$ sudo yum install docker-ce docker-ce-cli containerd.io
Copy the code

This will install the latest version, or you can choose to install the specified version

View the version list:

$ yum list docker-ce --showduplicates | sort -rLoading mirror speeds from cached hostfile Loaded plugins: Fastestmirror Installed Packages Docker-ce.x86_64 3:20.10.0-3.EL7 Docker-CE-Stable Docker-CE.x86_64 3:20.10.0-3.EL7 X86_64 3:19.03.9-3.el7 docker-ce-stable docker-ce. X86_64 3:19.03.8-3.el7 docker-ce-stable X86_64 3:19.03.7-3.el7 docker-ce-stable docker-ce. X86_64 3:19.03.6-3.el7 docker-ce-stable docker-ce X86_64 3:19.03.4-3.el7 docker-ce-stable docker-ce. X86_64 3:19.03.3-3.el7 Docker-ce-stable docker-ce X86_64 3:19.03.2-3.el7 docker-ce-stable docker-ce. X86_64 3:19.03.14-3.el7 docker-ce-stable .Copy the code

Select the specified version to install

$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
Copy the code

After the installation is complete, check the version

$ docker -v
Docker version 20.10.0, build 7287ab3
Copy the code

3. Start Docker

$ sudo systemctl start docker
Copy the code

Close the docker

$ sudo systemctl stop docker
Copy the code

Restart the docker

$ sudo systemctl restart docker
Copy the code

4. Mirror Image

**Docker packages the application and its dependencies in an image file. ** Only from this file can you generate a Docker Container. The image file can be thought of as a template for the container. Docker generates instances of containers from the image file. The same image file can generate multiple container instances running at the same time.

Image files are universal, and can be copied from one machine to another. In general, to save time, we should try to use image files made by others rather than making them ourselves. Even if you want to customize it, it should be based on someone else’s image file, not from scratch.

There is an official image library Docker Hub, many environment images can be pulled from it.

4.1 Viewing A Mirror

$ docker images
Copy the code

or

$ docker image ls
Copy the code

Just installed Docker, there is no image

$ docker image ls
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
Copy the code

Only all mirror ids are displayed

$ docker images -q
#or
$ docker image ls -q
Copy the code

4.2 Downloading an Image

Here we try to download an nginx image from the official library. The image is similar to the NPM global dependency. After pulling the image, all nginx images that need to be used can rely on the nginx.

Download the nginx image at hub.docker.com/_/nginx

$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
6ec7b7d162b2: Pull complete 
cb420a90068e: Pull complete 
2766c0bf2b07: Pull complete 
e05167b6a99d: Pull complete 
70ac9d795e79: Pull complete 
Digest: sha256:4cf620a5c81390ee209398ecc18e5fb9dd0f5155cd82adcbae532fec94006fb9
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    ae2feff98a0c   13 hours ago   133MB

Copy the code

Docker images displays the nginx image, with 5 titles, including the image name, TAG, id, creation time, and size. The default TAG is latest latest version, followed by the version number

$Docker pull nginx: 1.19
Copy the code

4.3 Deleting a Mirror

To delete a mirror, run the following command

$ docker rmi [image]
Copy the code

or

$ docker image rm [image]
Copy the code

[image] Can be the image name + label, or the image ID, ru

$ docker rmi nginx:latest
$ docker rmi ae2feff98a0c
Copy the code

Deleting all Mirrors

$ docker rmi $(docker images -q)
Copy the code

Delete all None mirrors

Some subsequent operations will repeatedly create the same mirror, the original mirror will be overwritten into, can be deleted in batches

$ docker rmi $(docker images | grep "none" | awk '{print $3}')
Copy the code

4.4 Creating an Image

We downloaded the Nginx image above, but to run our own project, we need to make an image of our own project and then generate the container to run the project.

To make an image, you need to use a Dockerfile file, using the admin background interface of this project as an example (or any HTML file), because it can be packaged and accessed only using Nginx.

First, run the command NPM run build under admin to generate the build folder, and create the index. HTML file. Then create the Dockerfile file under admin/docker

FROM nginx

COPY ../build /usr/share/nginx/html

EXPOSE 80
Copy the code

Put the build and docker folders in the same directory on the server, for example, /dockerProject/admin

├─admin └─build ├─ index.html ├─ trashCopy the code

Run the command in the docker directory

$ docker build ./ -t admin:v1Sending build context to Docker Daemon 4.096kB Step 1/3: FROM nginx ---> ae2feff98a0cStep 2/3 : COPY .. /build /usr/share/nginx/html COPY failed: forbidden path outside the build context: .. /build ()Copy the code

/ Based on the current directory as the build context, -t specifies the name of the image to be made.

You can see that there is an error,

The path must be inside the context of the build; you cannot ADD .. /something/something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

Once the build context is determined, some intermediate file operations can only be performed between the current contexts. There are two ways to resolve this problem

  1. Dockfile is in the same directory as build

    ├ ─ admin └ ─ build └ ─ index. The HTML └ ─ DockerfileCopy the code

    Dockerfile:

    FROM nginx
    
    COPY ./build /usr/share/nginx/html
    
    EXPOSE 80
    Copy the code

    Run commands in the admin directory

    $ docker build ./ -t admin:v1Sending build context to Docker Daemon 3.094MB Step 1/3: FROM nginx ---> ae2feff98a0c
    Step 2/3 : COPY ./build /usr/share/nginx/html
     ---> Using cache
     ---> 0e54c36f5d9a
    Step 3/3 : EXPOSE 80
     ---> Using cache
     ---> 60db346d30e3
    Successfully built 60db346d30e3
    Successfully tagged admin:v1
    Copy the code
  2. Dokcerfile is still put into docker for unified management

    ├─admin └─build ├─ index.html ├─ trashCopy the code

    Dockerfile:

    FROM nginx
    
    COPY ./build /usr/share/nginx/html
    
    EXPOSE 80
    Copy the code

    Run commands in the admin directory

    $ docker build -f docker/Dockerfile ./ -t admin:v1Sending build context to Docker Daemon 3.094MB Step 1/3: FROM nginx ---> ae2feff98a0c
    Step 2/3 : COPY ./build /usr/share/nginx/html
     ---> Using cache
     ---> 0e54c36f5d9a
    Step 3/3 : EXPOSE 80
     ---> Using cache
     ---> 60db346d30e3
    Successfully built 60db346d30e3
    Successfully tagged admin:v1
    Copy the code

    Notice the./build path here. -f (-file) specifies a Dockfile file./ uses the current path as the build context, so the build path is still./build

The Dockerfile file is used above, but it will not be described here because it is relatively small, and will be explained later when deploying next.js.

5. The Container vessel

Let’s take a look at the admin:v1 image generated above

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
admin        v1        60db346d30e3   51 minutes ago   136MB
nginx        latest    ae2feff98a0c   14 hours ago     133MB
Copy the code

If you want to create an nginx image, you need to create an nginx image. If you want to create an nginx image, you need to create an nginx image.

The project runs inside a container, and we need to create a container with an image.

5.1 Viewing Containers

$ docker container ls
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS          PORTS          NAMES
Copy the code

or

$ docker ps
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS          PORTS          NAMES	
Copy the code

These two commands display only the containers that are running, not the containers that are stopped, and the -a (–all) argument will display all of them

$ docker container ls -a
$ docker ps -a
Copy the code

View only all container ids

$ docker ps -aq
Copy the code

5.2 Generating Containers

Here we generate a container with admin:v1

$ docker create -p 9001:80 --name admin admin:v1
Copy the code
  • -p: port mapping. Host (server) : container. 9001:80 indicates that port 9000 of the host can access port 80 of the container
  • –name: generated container name, unique value
  • Admin :v1: used mirror and label:v1The default is:latest

There are many parameters, can understand docs.docker.com/engine/refe…

Now that the container is generated, let’s see

$ docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d755bab5C73 admin:v1 "/ docker-entryPoint...." 5 minutes ago Created adminCopy the code

You can see that the container has been generated, but it is not running yet, so all ps using Docker are invisible

Run the container: docker start [container iD], [] can use the container iD, can use the container name, both are unique

$ docker start admin

$ docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d755bab5C73 admin:v1 "/ docker-entryPoint...." 8 minutes ago Up 3 seconds 0.0.0.0:9001->80/ TCP adminCopy the code

The container is running, and you can access the container through the server IP address + port 9001 (Mac address, Windows directly localhost:9001).

The above generates containers, which can also be run with a command

$ docker run -p 9001:80 --name admin admin:v1
Copy the code

5.3 Deleting a Container

To delete a container, run the following command

$ docker rm admin # id or name
Copy the code

Stop the container if it is running

$ docker stop admin
Copy the code

Or forcibly delete

$ docker rm -f admin
Copy the code

Stop all containers

$ docker stop $(docker ps -aq)
Copy the code

Delete all containers

$ docker rm $(docker ps -aq)
Copy the code

Stop and delete all containers

$ docker stop $(docker ps -aq) & docker rm $(docker ps -aq)
Copy the code

5.4 Container Logs

If the container fails to run, you can view the logs to locate the error

$ docker logs admin
Copy the code

5.5 Entering the Container

A container is like a file system, and we can also go inside and look at the files inside. Use the following command to enter the container

$ docker exec -it admin /bin/sh
Copy the code
  • -iThe argument keeps the container’s standard input on, –interactive
  • -tThe argument lets Docker assign a dummy terminal and bind it to the container’s standard input, –tty
  • Admin: indicates the container ID or name

Once inside the container, you can access the internal files using Linux commands

$ ls
bin  boot  dev	docker-entrypoint.d  docker-entrypoint.sh  etc	home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

$ cd usr/share/nginx/html
$ ls
50x.html  asset-manifest.json  favicon.ico  index.html	manifest.json  robots.txt  static
Copy the code

The default nginx HTML directory is usr/share/nginx/ HTML, and you can see the file we copied from the Dockfile

6. docker-compose

Docker-compose can be composed by using a simple command. Of course, this is only a small part of its functions. Docker-compose can be composed by using a simple command.

The official synopsis is as follows:

Compose is a tool for defining and running multi-container Docker applications. With Compose, you can use YAML files to configure your application’s services. Then, with a single command, you can create and start all the services from the configuration.

Using Compose is basically a three-step process:

  • Use Dockerfile to define the application’s environment so that it can be copied anywhere.
  • Define the services that make up your application in docker-comemage.yml so that they can run together in an isolated environment.
  • Run docker-compose up, and compose starts up and runs the entire application.

6.1 installation docker – compose

Refer to the official documentation Install Docker Compose for a brief introduction to Linux installation

  1. Run the command

    Sudo curl - L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname - s) - $(uname -m)" - o /usr/local/bin/docker-composeCopy the code

    If the installation is slow, you can download it using DaoCloud

    Sudo curl -l https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose- ` ` uname - s - ` uname -m ` - o /usr/local/bin/docker-composeCopy the code
  2. Add executable permissions

    sudo chmod +x /usr/local/bin/docker-compose
    Copy the code
  3. Check whether the installation is complete

    docker-compose --version
    Copy the code

6.2 docker – compose. Yml

Docker-compose. Yml is docker-compose runtime file, which is configured with some parameters of the image and container, here to implement the above image creation, generate container, run container.

version: '3'
services:
  admin:
    build: 
      context: ../
      dockerfile: ./docker/Dockerfile
    image: admin:v1
    ports: 
      - 9001: 80
    container_name: admin
Copy the code

Configuration parameters have many docs.docker.com/compose/com… , the official website can be explained in detail, here and later only talk about some of the configuration used.

  • Varsion: Optional 1, 2, 2.x, 3.x
  • Services: indicates a service group
    • Admin: service name, unique, multiple docker-comemage. yml have the same name, the following container will overwrite
      • Docker-comemage. yml, Dockfile, Dockfile, Dockfile, and docker-comemage. yml If docker-comemage. yml and Dockfile are stored in the docker folder, specify the build context context and dokcerfile
      • Context: Build context
      • Dockerfile: Specifies the path to the dockerfile
    • Image: Specifies the image to use. If the image exists, it will be used directly, otherwise it will be built using the dockerfile above
    • Ports: Multiple ports can be mapped. In the file – means the argument is an array, and can be multiple
    • Container_name: specifies the name of the container. if not specified, this defaults to the current directory _admin_index.

Put docker-comemage. yml into the docker directory

├─admin └─build ├─ index.html ├─ docker ├─ docker-teach.ymlCopy the code

Run in the docker directory

$ docker-compose up -d --build
Copy the code
  • -d: indicates the daemon running in the background. If no -d is added, the build process will be displayed. Finally, you can only exit with Ctrl + C, and the container will stop and start again
  • –build: indicates that the Dockerfile will be re-executed for each build (NPM package will be re-installed). Otherwise, if the image exists, the Dockerfile will not be executed

Docker-compose is in the same directory as build

├─admin └─build ├─ index.html ├─ docker-teach.txtCopy the code

The docker – compose. Yml

version: '3'
services:
  admin:
    build: . /
    image: admin:v1
    ports: 
      - 9001: 80
    container_name: admin
Copy the code

Run it in the build directory

$ docker-compose up -d --build
Copy the code

The word is over, to be continued, deployment ~